---
url: /docs/agentbuff-stack/auth-key-rotation.md
---
# 认证密钥轮换

本教程对应 I15 的认证操作准备，当前已完成实际本地 Worker 重启、原账号与收费任务验收；真实云端仍待明确环境后验证。每站、每环境单独保存密钥，操作文件放在版本控制之外，公开页面与构建参数不放私钥。

## 配置与默认行为

`BETTER_AUTH_SECRET` 仍必填，至少 32 字符。它既是旧格式认证加密的后备密钥，也用于模板自己的营销链接、通知接收人和投递目标摘要。

新增可选 `BETTER_AUTH_SECRETS`，采用按顺序排列的 `版本:密钥`，条目用逗号分隔。第一个版本用于新认证签名和加密，其余版本供库读取对应的旧加密数据。空值视为未配置，此时明确使用版本 0 和 `BETTER_AUTH_SECRET`；原旧格式密文仍由基础密钥读取，新的带版本密文使用版本 0。

版本是非负安全整数，0 可用，不接受前导零、重复版本或同值不同版本。最多十项，每个密钥为 32—1024 字符且不含空白；使用独立生成的随机值。环境检查仅报告字段与问题类别，诊断只显示版本号，不显示密钥值。直接传递显式配置，防止认证库另选进程中的密钥列表。

这项能力复用已安装 Better Auth 1.7.4 的版本配置，没有另外实现加密算法或密钥服务。[官方轮换说明](https://better-auth.com/docs/reference/security)限定于相同加密格式和用途：保留旧密钥用于解密，数据在后续写入时采用当前密钥。核对日期 2026-10-11。具体 Cookie 行为仍以本项目安装版本的实际验收为准。

## 先区分轮换目的

正常切换当前认证密钥时，可保留此前密钥作为读取过渡，并保持基础密钥不变。这样模板自己的邮件选择、营销链接和投递摘要继续沿用原密钥。

旧密钥泄露后的撤销需要移除所有仍接受它的配置，包括版本列表与 `BETTER_AUTH_SECRET` 后备。保留已泄露密钥不能达到撤销目的。与此同时，历史密文、旧营销链接和通知选择可能失效，需先确定恢复 / 重新确认与退订处理安排。

## 过渡阶段

以下仅示意格式，用自己的实际随机密钥替换括号内容，不将示例复制为可用凭据：

```dotenv
BETTER_AUTH_SECRET=<现有基础密钥>
BETTER_AUTH_SECRETS=1:<新随机密钥>,0:<现有基础密钥>
```

0 是当前模板未配置版本列表时的版本；已有自定义版本列表的站点保留其实际旧编号和密钥，不改编号来冒充重写历史密文。先在独立测试环境核对配置，再让同一认证入口的实例使用一致的当前版本。

```sh
bun --env-file .env.staging.local scripts/config-check.ts --target staging
```

真实 Worker 的秘密需由操作者在所选环境保存，电脑上的私有环境文件不会自动进入云端。轮换与部署不是原子切换，混合当前版本的实例可能相互拒绝 Cookie；实际发布仍按[部署教程](./deployment)明确范围执行。

**本版本实测：切换第一个认证密钥后，原登录 Cookie 返回未登录，原密码重新登录成功。** 保留旧版本并不保证已有会话连续可用。重新登录后的账号、积分、原文件和收费任务继续使用原数据库记录；轮换不会自动执行任务、再次扣费或提高账号权限。正在进行的认证 / OAuth 回跳需重新开始，真实第三方回跳另行验收。

## 撤销旧密钥

先核对仍依赖旧版本或旧格式的加密数据与待完成认证流程。库只在相应数据再次写入时采用新密钥，模板没有批量重写历史密文的操作；从配置删除旧版本不代表数据已迁移。不可读的历史密文不能靠恢复同一数据库备份自动变为新密钥密文。

确认所需数据可用及基础用途处理方式后，示意配置为：

```dotenv
BETTER_AUTH_SECRET=<新基础密钥>
BETTER_AUTH_SECRETS=1:<新随机密钥>
```

新基础密钥可与当前认证密钥相同，亦可独立安排；在新配置内检查各自用途，确保旧密钥确实不再被接受。只删除版本 0 却保留原基础密钥，仍可能通过旧格式后备读取旧密文。

| 用途 | 当前边界与处理 |
| --- | --- |
| 认证 Cookie | 已用当前密钥重新登录的 Cookie 在只删除旧版本、当前密钥不变时继续有效；仅基础密钥变化不等于撤销全部会话 |
| 历史加密内容 | 旧版本 / 旧基础密钥移除后相应内容可能无法解密；需保留读取能力或先完成实际重写 / 重新认证验收 |
| 任务邮件选择 | 基础密钥变化后旧接收人摘要不再匹配，原账号需在设置中明确重新确认；不能自动假定仍可发送 |
| 站主通知 | 基础密钥变化会改变目标摘要，待发送记录按原规则复核 / 停止；实际 Discord 目标与投递仍须验收 |
| 营销确认与退订链接 | 由基础密钥签名，认证版本列表不参与验证。基础密钥变化后旧链接失效，需安排有效退订通道和站主处理；模板没有批量重签历史链接命令 |
| 用户 API Key 与外部服务 | 使用各自的签发 / 撤销和供应商密钥，不把认证密钥轮换当成它们已全部撤销 |
| 数据库、R2、队列与权限 | 独立核对凭据、绑定、访问角色和历史状态；本教程不会替操作者修改云资源或数据库角色 |

营销同意、订阅状态与签名链接不同；链接失效不会自动将联系人退订，也不会证明供应商已停止投递。轮换期间保持可用的退订与联系处理方式，原供应商同步和管理员恢复按[营销教程](./marketing-subscriptions)处理。

## 本地复验与证据

```sh
bun auth:validate-rotation
```

命令只接受回环 PostgreSQL，创建自己的完整迁移数据库和隔离 Worker / R2 目录。实际注册、上传、报价确认、扣 3 积分并完成任务；销毁 / 重启 Worker 两次，验证当前密钥切换后的旧 Cookie 拒绝、密码重新登录、旧密钥撤销后当前 Cookie 继续访问原私有结果。账户始终为普通用户，余额 17、原任务编号和一次尝试保持，重复请求不再次扣费。

任务邮件使用合成的邮箱资格记录和实际明确选择，未验证外部邮箱。过渡期选择有效，基础密钥撤销后有效选择变为关闭，再通过原设置接口重新确认。实际配置诊断同时验收合法 / 非法列表与输出不含秘密；认证库的旧格式 / 版本密文、当前写入和撤销拒绝另由回归测试验证。

结束删除本次数据库、资源目录与会话，不修改正常主预览的密钥或账号。真实 Cloudflare 发布、OAuth / Passkey 回跳、历史加密记录处理、外部投递和访问权限仍需在明确的测试环境验收，完整 I0—I16 目标继续保留。
