> For the complete documentation index, see [llms.txt](https://docs.convai.com/api-docs/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://docs.convai.com/api-docs/zh/cha-jian-yu-ji-cheng/convai-unity-sdk/authentication/ship-a-secure-build.md).

# 发布安全构建

以 Auth Token 模式构建 Convai Unity SDK 玩家，使账户 API Key 永远不会进入已发布构建，并满足 WebGL 的 CORS 要求。

生成一个不包含 Convai 账号 API 密钥的播放器构建，并配置一个 WebGL 构建实际可访问的令牌端点。在 [配置 Auth Token 模式](/api-docs/zh/cha-jian-yu-ji-cheng/convai-unity-sdk/authentication/configure-auth-token-mode.md)，就在你构建之前立即。

### 构建处理器的作用

`ConvaiApiKeyStripBuildProcessor` 会在每次构建前运行。如果 **认证模式** 是 **身份验证令牌**，它会将这两个字段都清零： `_apiKey` 和 `_apiKeyObfuscated` 字段，在项目的 `ConvaiSettings` 资源在构建期间置空，然后在之后恢复已保存的密钥。如果 **认证模式** 是 **API 密钥**，则处理器不会执行任何操作——账号密钥会照常包含在构建中。

清除操作只会影响 `ConvaiSettings` ，并且仅在构建运行期间。它会在清除前将备份写入 `Library/Convai/AuthTokenBuildCredentialBackup.json` ，因此即使 Editor 崩溃或构建进程被终止，密钥也能保留，并会自动恢复：

* 构建完成后（`OnPostprocessBuild`),
* 如果构建被中断或取消（`EditorApplication.update`),
* 在 Editor 带着未处理的备份退出之前（`EditorApplication.quitting`).

{% hint style="warning" %}
你保存的 API 密钥始终可供 Editor 工具使用——Play 模式、仅限 Editor 的回退令牌提供器以及其他 Editor 工作流程都会继续正常运行。只有磁盘上的 `ConvaiSettings` 用于构建的资源会被清空，而且仅在构建期间如此。
{% endhint %}

### 构建会失败关闭，而不是失败开放

如果处理器无法保证密钥不存在，它会以以下错误停止构建： `BuildFailedException` 而不是发布一个未清除的密钥。你可能会遇到以下这些确切消息之一：

| 控制台消息                                                                            | 原因                                                                                                                                  |
| -------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------- |
| `Convai 无法恢复先前中断的构建遗留的凭据。为避免丢失已保存的 API 密钥，新构建已停止。`                               | 之前的构建留下了一个从未恢复的待处理备份。打开 **Convai > Settings > Credentials** 以触发恢复，或者检查 `Library/Convai/AuthTokenBuildCredentialBackup.json`，然后重新构建。 |
| `Convai Auth Token 模式在构建前需要一个已保存的 ConvaiSettings 资源。`                            | 项目中没有已保存的 `ConvaiSettings` 资源。打开 **Convai > Settings** 一次，让 SDK 创建它。                                                                |
| `Convai Auth Token 模式要求 ConvaiSettings 资源位于此项目中，而不是包内——从包资源中清除密钥不会以构建所依赖的方式被保存。` | 设置资源解析到了包路径而不是项目路径。请将该资源移动到项目内或在项目内重新创建。                                                                                            |
| `Convai 无法定位序列化的 API 密钥字段。构建已停止，因为 Auth Token 模式无法保证账号密钥不存在。`                    | 该 `ConvaiSettings` 资源的序列化布局与处理器预期不符，通常是因为对该资源进行了自定义修改。请从已知正常的副本恢复该资源。                                                               |

清除成功时，Console 会记录 `[Convai] 已为此 Auth Token 播放器构建临时移除已存储的 API 密钥。构建完成后会在 Project Settings 中恢复。`，并且在构建恢复它之后， `[Convai] 播放器构建后已恢复 Project Settings 中的 API 密钥。`

### 已存储的密钥是混淆的，不是加密的

`ConvaiApiKeyObfuscation` 会使用一个固定密钥字符串应用 XOR 密码，然后将结果通过 Base64 编码，并加上 `cnv1:` 前缀。这样可以避免在序列化资源和版本控制差异中轻易被 grep 到 API 密钥——这不是加密。任何拥有 SDK 源码的人都可以将其还原，而任何随客户端构建一起发布的密钥最终都可以被提取出来。

{% hint style="danger" %}
不要把混淆当作安全措施。如果你将 API Key 模式的构建发布给你无法完全控制的受众，账号密钥可以从该构建中恢复。任何离开你自己机器的构建都应使用 Auth Token 模式发布。
{% endhint %}

### 满足 WebGL 的 CORS 要求

WebGL 构建会从浏览器访问你的令牌端点，因此该端点需要的不只是 HTTPS。请在以 Auth Token 模式分发 WebGL 构建之前，确认你的后端满足以下所有条件：

* 使用 HTTPS。SDK 会拒绝任何非 HTTPS 或非 HTTP 回环地址的端点，而且浏览器无论如何都会阻止从 HTTPS 页面发出的混合内容请求。
* 通过 CORS 允许已部署游戏的准确来源（origin）——当请求携带凭据或 cookie 时，不能使用通配符来源。
* 允许 `Authorization` 和 `Content-Type` 请求头。
* 响应 CORS 预检（`OPTIONS`）请求。

如果你的登录系统使用 cookie 而不是 bearer token，还要配置 `Secure`, `HttpOnly`，以及适当的 `SameSite` 值，添加 CSRF 防护，并在依赖它之前确认浏览器从 Unity WebGL 实际发送凭据的方式。

原生构建和 WebGL 构建会使用相同的请求头发送解析后的令牌， `API-AUTH-TOKEN` ——不存在 WebGL 专用请求头。上面的 CORS 要求之所以存在，是因为浏览器会对发往你端点的出站请求强制执行这些限制；原生构建没有这种限制。

### 验证构建是否干净发布

在生成 Auth Token 模式构建后，确认账号 API 密钥不存在：

1. 在构建期间检查 Console 中是否有 `[Convai] 已为此 Auth Token 播放器构建临时移除已存储的 API 密钥。` 如果没有出现这一行，则构建是使用 **认证模式** 设置为 **API 密钥**，而不是 **身份验证令牌**，并且密钥已被包含。
2. 构建完成后，确认 `[Convai] 播放器构建后已恢复 Project Settings 中的 API 密钥。` 出现，并且 **Convai > Settings > Credentials** 在 Editor 中仍显示你保存的密钥。
3. 运行已构建的播放器，并确认角色成功连接。成功连接表明你注册的提供者或配置的端点在运行时提供了有效令牌。

### 下一步

<table data-view="cards"><thead><tr><th></th><th data-hidden data-card-target data-type="content-ref"></th></tr></thead><tbody><tr><td><strong>排查身份验证问题</strong><br>两种认证模式的控制台消息和错误代码。</td><td><a href="/api-docs/zh/cha-jian-yu-ji-cheng/convai-unity-sdk/authentication/troubleshooting.md">身份验证故障排查</a></td></tr><tr><td><strong>配置 Auth Token 模式</strong><br>切换到 Auth Token 模式，并在 Project Settings 中配置令牌端点。</td><td><a href="/api-docs/zh/cha-jian-yu-ji-cheng/convai-unity-sdk/authentication/configure-auth-token-mode.md">配置 Auth Token 模式</a></td></tr></tbody></table>


---

# Agent Instructions
This documentation is published with GitBook. GitBook is the documentation platform designed so that both humans and AI agents can read, navigate, and reason over technical content effectively. Learn more at gitbook.com.

## Querying This Documentation
If you need additional information that is not directly available in this page, you can query the documentation by asking a question.

Perform an HTTP GET request on the following URL with the `ask` and `goal` query parameters:

```
GET https://docs.convai.com/api-docs/zh/cha-jian-yu-ji-cheng/convai-unity-sdk/authentication/ship-a-secure-build.md?ask=<question>&goal=<user_goal>
```

`ask` is the immediate question: it should be specific, self-contained, and written in natural language.
`goal` is what the user is ultimately trying to achieve, the reason they need the answer. Sharing it helps GitBook give you a better, more relevant answer. A goal is most helpful when it describes the outcome the user wants rather than restating the question. For example, with `ask=how do I create an API token`, a goal like `automate deployments from our CI pipeline` lets GitBook tailor the answer to that use case.

The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
