---
type: explanation
title: 游戏反作弊
summary: 游戏如何不只是一个挑战。一套分层的反作弊系统，它在服务器上把每个回合搭建好、在浏览器里把它沙箱化地跑、并通过确定性回放重新核验它。
---

访客玩上几秒的那个游戏是你看得见的那部分。它底下是那套让游戏算作一个人类证明的反作弊系统。Caputchin 借用竞技多人游戏对付作弊者的那套打法：服务器对每个回合权威、游戏在一个锁死的沙箱里跑、而结果通过重放玩家的输入来重新推导。这个游戏可以被玩，但作不了假。

这是第三道验证关卡，和 [proof of work](/docs/understanding-caputchin/proof-of-work) 与 [探测](/docs/understanding-caputchin/instrumentation) 叠在一起。它在 [安全](/docs/site-keys/security) 页上按密钥配置。

## 这个生命周期

一个回合走过三个阶段：在游玩前于服务器上搭建、在游玩中于浏览器里沙箱化地跑、并在游玩后于服务器上重新核验。

```mermaid
sequenceDiagram
    participant V as 访客浏览器
    participant S as Caputchin 服务器
    participant G as 沙箱化的游戏 iframe
    participant R as 回放隔离体
    V->>S: 请求一个挑战
    S->>V: 签名的一次性票据（服务器挑游戏和种子）
    V->>G: 在一个隔离的 iframe 里挂载游戏
    Note over G: 无网络，够不到你的页面
    G->>V: 把玩家的输入记录成一条轨迹
    V->>S: 提交票据和轨迹
    S->>R: 在同一个种子下重跑这条轨迹
    Note over R: 密封、无网络、有时限
    R->>S: 裁定与分数
    S->>V: 签名的令牌，仅当回放确认了这次游玩时
```

## 回合之前：服务端权威的搭建

决定这个回合 *是什么* 的一切都发生在服务器上，绝不在浏览器里。这就是多人游戏反作弊里那条“永不信任客户端”的原则：客户端发送意图，服务器决定现实。

- **一张签名的、一次性的票据** 铸造这个回合。它短时有效，且只能花一次。一张被截获的票据无法被重放成第二次通过。
- **游戏和它的随机种子在服务端被选定**，并装在票据里。浏览器无法挑一个更容易的游戏或一个更友好的种子，因为它从不做那个选择。
- **每次都从合格池里换一个不同的游戏。** 一个求解器从不知道它会面对哪个游戏，所以它无法在单一的静态目标上预先训练。运营者可以收窄轮换，但服务器总是从被允许的集合里挑。这个池本身只包含通过了一次索引时一致性检查的游戏。见 [构建一个应用市场游戏](/docs/marketplace-game-development/build-a-marketplace-game)。

## 回合之中：一个沙箱化的游戏

游戏在访客的浏览器里跑，但在一道既保护访客站点、又保护这个回合完整性的边界之内。

`<caputchin-game>` 把每个游戏挂载在一个没有同源访问权的隔离 iframe 里，于是这个游戏有一个不透明的来源，够不到宿主页的 cookie、存储、DOM 或同源网络。它内联的 content-security-policy 把脚本钉死到恰好是这个游戏的包，并挡住出站的网络调用，而这个包在运行前会对着一个已知的哈希被检查（不匹配则失败关闭）。宿主页自己的安全策略原封不动。精确的沙箱和策略形状记录在 [Caputchin 如何沙箱化游戏](/docs/understanding-caputchin/game-sandboxing) 里。

要点：游戏默认不被信任并被收容。它无法把任何东西外泄，也无法篡改它所嵌入的那个页面。

## 回合之后：确定性回放

当访客完成时，浏览器提交记录下来的输入轨迹。服务器不会就结果听信浏览器的话。它重跑这条轨迹。

- **回合在服务器上被重新模拟**，在同一个服务端派生的种子下，在一个没有网络访问、带一个硬时间预算的密封隔离体里。这就是确定性锁步在策略游戏里所依赖的同一种性质：相同的种子加相同的输入，重现相同的游玩。一条没真正通过游戏的轨迹不会重现出一个通过的结果。
- **通过还是失败从那次回放里取**，绝不从浏览器报告的一个数字里取。一个客户端无法声称一个它没挣到的分数。
- **一个签名的令牌仅当回放确认了这次游玩时才被签发。** 当你的后端日后在验证时确认它时，那个令牌本身也是一次性的。

## Caputchin 不做什么

大多数游戏式和交互式 CAPTCHA 倚靠行为信号：鼠标轨迹熵、点击时机、喂给一个分类器去猜机器人对真人的设备遥测。Caputchin 有意不这样。它不采集玩家的任何行为画像。它不去猜这些输入是 *如何* 产生的，而是从第一性原理重新推导它们 *是否* 真的通过了游戏。这既是一种隐私姿态、也是一种安全姿态：没有行为模型可骗，只有物理可重现。

## 一个诚实的局限

**关卡只和游戏一样强。** 反作弊机件证明一个回合是被真正玩过的、没作假，但它无法让一个简单的游戏变难。一个微不足道的游戏（一个静态棋盘、获胜的一步在 DOM 里可读、“点红点即过”）对一个脚本来说求解便宜，而确定性回放会忠实地确认那些脚本化的输入获胜，因为它们确实获胜。对机器人的抵抗力来自游戏本身难以被程序化地求解：快速、感官、零点几秒的反应，且没有解坐在 DOM 里。反作弊层保证这次游玩是真的；游戏的设计决定真实的游玩是否难以被自动化。怀着这个去挑选和构建游戏，见 [构建一个应用市场游戏](/docs/marketplace-game-development/build-a-marketplace-game)。

通过还是失败由每个游戏自己的逻辑决定；服务器忠实地重跑那个逻辑，但不去质疑一个给定游戏认为什么算获胜。游戏反作弊在和 [proof of work](/docs/understanding-caputchin/proof-of-work)、[探测](/docs/understanding-caputchin/instrumentation) 以及一个密钥其余的 [安全设置](/docs/site-keys/security) 组合在一起时最强。
