章节导航 第 14 章 / 共 23 章
认证与多云适配
OAuth 2.0 + PKCE 认证流程、令牌源优先级、WIF 零静态密钥、AWS Bedrock(含 Mantle 端点)/ Azure Foundry / Google Cloud's Agent Platform 三大云平台适配
14.1 四种认证方式
Claude Code 支持四种认证方式,覆盖从个人开发者到企业级部署的全部场景:
| 认证方式 | 适用场景 | 凭证类型 |
|---|---|---|
| OAuth 2.0 + PKCE | Claude.ai 订阅用户 | Access Token + Refresh Token |
| API 密钥 | 直接 API 调用 / CI/CD | API Key |
| 多云认证 | AWS Bedrock / GCP Vertex / Azure Foundry | 云平台凭证 |
| Workload Identity Federation | 企业级零静态密钥部署 | 短效访问令牌 |
令牌源按以下优先级检查(官方为 7 级):
- Cloud provider credentials——设置了
CLAUDE_CODE_USE_BEDROCK/CLAUDE_CODE_USE_VERTEX/CLAUDE_CODE_USE_FOUNDRY时 ANTHROPIC_AUTH_TOKEN——以Authorization: Bearer头发送,用于经 LLM 网关或代理路由的场景ANTHROPIC_API_KEY——以X-Api-Key头发送,用于 Claude Console 密钥直连apiKeyHelper脚本输出——用于从 vault 获取短效令牌的动态/轮换凭证CLAUDE_CODE_OAUTH_TOKEN——claude setup-token生成的长生命周期 OAuth 令牌,用于无法浏览器登录的 CI 与脚本- Anthropic profile and federation credentials——
antCLI 与 Workload Identity Federation 使用的凭证 - Subscription OAuth credentials from
/login——Claude Pro / Max / Team / Enterprise 用户的默认方式
⚠️ 原稿两处偏差已更正。其一,原稿标题称「8 级」但只列 7 条,多出的编号是插入在第 1 级之后的非标准
1.5(Claude apps gateway session)。官方的表述是:gateway session 不在这个列表内(sits outside this list)——它是与 Bedrock、Google Cloud’s Agent Platform 同级的 provider selection,且优先级高于它们。存在 gateway session 时,即使设置了CLAUDE_CODE_USE_BEDROCK等变量,CLI 仍用 gateway token 认证,上面第 2–6 级的 bearer token / API key /apiKeyHelper/ profiles 一概不被使用。把它塞进编号链会让人误以为它只是”插队的一级”。其二,也是更要紧的一处:原稿完全缺了官方第 6 级。本章 14.1 把 WIF 列为四种认证方式之一,但优先级表没给 WIF 凭证任何位置——读者按原表排查”为什么我的 WIF 没生效”,会误以为 WIF 排在
/login之后。实际它排在/login之前(详见 14.3.1)。
gateway session 小结:它是 provider selection,不是优先级条目;优先级高于所有云提供商变量;存在时上面第 2–6 级均不生效。若托管设置把 forceLoginMethod 设为 "gateway" 或设置了 forceLoginGatewayUrl,且未通过变量选择云提供商,则会话只使用 gateway 登录。
apiKeyHelper TTL 配置:CLAUDE_CODE_API_KEY_HELPER_TTL_MS 环境变量自定义刷新间隔(默认 5 分钟或 HTTP 401 触发),若响应超过 10 秒则显示慢速警告。
第五条通道:证书客户端认证(private_key_jwt)。上表四种方式覆盖的是客户端与 Anthropic(或云)之间的认证。v2.1.284 起还有一条方向不同的通道:Claude apps gateway 与它的 IdP 之间支持 private_key_jwt——面向那些颁发证书凭证而不是 client secret 的 IdP。它不改变客户端的认证方式,改的是网关替你去做 OIDC 时拿什么证明自己。把它列在这里的理由是:排查「网关侧登录失败」时只看客户端凭证是不够的,还有一层网关↔IdP 的认证。
2026-10-19 回源复核:这张表逐条未变。 7 级顺序(云凭证 → ANTHROPIC_AUTH_TOKEN → ANTHROPIC_API_KEY → apiKeyHelper → CLAUDE_CODE_OAUTH_TOKEN → profile/federation → /login)、gateway session “sits outside this list” 的措辞、14.3.1 的 WIF 三源排序表与 user_oauth 例外、以及 bare mode / Desktop / cloud sessions 的边界——与官方 iam 文档逐条一致。
按本书体例,“确认没变”也要留痕,而且它有一个方法论含义值得写下来:这张表之所以稳定,是因为它是按官方原文重列的,而不是按行为推断的。 推断出来的顺序会随实现漂移,抄下来的顺序只会随文档变更。下一次修订者看到这一段,可以判定它不需要重查。
策略的到达条件:配了不等于发了,发了不等于到达。 上面讲了”有托管登录策略时优先链不作数”,但还缺一个更前的条件——策略本身能不能到达这台客户端。Server-managed settings 只能触达已经认证进组织的账号,因此无法用于引导开发者的首次登录;这是它与设备侧托管设置的分工边界,而不是缺陷。
更需要注意的是两类托管源不合并:cached server-managed settings 会整体替换设备侧的托管文件,只有少数逐键例外。而 forceLoginOrgUUID 与 forceLoginMethod 的 "claudeai" / "console" 两个取值不在这些例外之内——这意味着这两个键必须在两处都写,只写一处会静默失效。
一句话结论:“配了”与”生效了”之间还有第三个条件——账号必须先认证进去;而两个分发渠道各写一半,会导致其中一半静默失效。
第四段:到了之后用哪份(v2.1.316)。 三段式之后还有一步——策略到达之后,客户端在「新拉取的副本」与「本地存档副本」之间还有一次真伪裁决:Team 与 Enterprise 登录的服务端托管设置现在无需批准提示即生效,但校验不过的存档副本会被拒绝使用。裁决失败的方向是 fail-closed——宁可回到无策略状态,也不带病运行(失效方向的完整讨论见 13.6.4)。到达语义至此形成四段:配了 ≠ 发了,发了 ≠ 到达,到了 ≠ 采纳,采纳 ≠ 长期有效(存档副本过期同样会被弃用)。
同一段链路上还有一条故障样本(v2.1.318 修复):setup-token 在设了 forceLoginOrgUUID 的机器上曾被整体拒绝——即使 token 属于允许的组织。这是优先级链与策略短路交叉处的又一实证 bug:合法凭证被组织策略一刀切掉,恰好是上文”有托管登录策略时优先链不作数”的最坏形态。配套的修复还有:登录到期时的失败信息现在会明确说原因,claude -p 输出中并点名 claude auth login / claude setup-token(v2.1.318);claude auth status 不再因慢速 token 刷新未保存而把人登出(v2.1.317)。
“不合并”还有一条对偶面需要澄清(v2.1.316)。 上面强调的两类托管源不合并,指的是设备侧与服务器侧两个分发渠道之间。但服务器侧内部,gateway 的 managed.policy_mode: layered 允许多条匹配策略叠加强制(每条命中的 policy 在其下层之上合并生效),取代了”只取第一条”的旧行为——“不合并”不是托管体系的普遍属性,而是两个特定分发渠道之间的行为;服务器侧的策略合并方向,恰好反过来。
托管登录策略会把优先级链短路,且现在会告诉你短路在哪一级。v2.1.284 起,当 managed settings 通过 forceLoginMethod 或 forceLoginOrgUUID 要求登录、而你又配置了 API key / token / apiKeyHelper 时,启动拒绝信息会点名正在使用的凭证、它的设置位置、以及如何移除。这与 14.3.1 的三源排序表是一体两面:那张表讲「没有任何策略干预时谁优先」,这条讲「有策略时优先链不作数」,并且把定位成本从上节的 ~/.claude/debug/ 日志搬到了启动报错里。
源码引用:认证系统核心参见 src/services/oauth/,多云认证参见 src/utils/auth.ts。
14.2 OAuth 2.0 + PKCE
Claude Code 的 OAuth 实现使用 PKCE(Proof Key for Code Exchange)扩展——这是针对公开客户端(无法安全存储 client secret 的应用)的安全增强。
认证流程:
1. 生成 code_verifier(随机字符串)
2. 计算 code_challenge = SHA256(code_verifier)
3. 构建授权 URL(包含 code_challenge)
4. 打开浏览器让用户登录
5. 本地启动 HTTP 服务器监听回调
6. 收到 authorization_code
7. 用 code + code_verifier 交换 access_token
8. 将 token 存储到 macOS 钥匙链 / 安全存储
终端代码粘贴(WSL2/SSH/容器)。v2.1.126 改进了 OAuth 登录:当运行在 WSL2、SSH 远程会话或容器中时,浏览器回调无法到达 localhost。此时 claude auth login 接受终端中粘贴的 OAuth 授权码,绕过浏览器回调限制。这一改进将 OAuth 登录成功率提升约 30%。
登录过期预警。v2.1.203+ 起,当 /login 凭证距过期 5 天内时,启动时显示警告”Your login expires in 3 days · run /login to renew”(仅对 claude.ai 或 Claude Console 登录生效)。这一机制帮助用户在凭证过期前主动续期,避免会话中断。
2026-11-04(v2.1.318)起这条预警长成了三层,且从「人来读」进化到「脚本能读」:
| 层 | 形态 | 窗口 | 版本 |
|---|---|---|---|
| 启动 UI 警告 | 启动时显示剩余天数 | 提前 5 天 | v2.1.203 |
claude auth status | 新增 loginExpiresAt 字段,可直接查凭证到期日 | 常驻 | v2.1.318 |
claude -p | JSON 结果新增 credential_expires_at;文本输出在到期前 10 天起输出一行 stderr 警告 | 提前 10 天 | v2.1.318 |
对 CI/CD 场景(14.1 第 5 级 CLAUDE_CODE_OAUTH_TOKEN 的主用户群)这是实质性改进:管道脚本现在可以提前十天自查凭证寿命——claude -p 的 stderr 一行警告足以触发任何监控系统,而不必等到管道中途失败。预警窗口翻倍(5→10 天)也说明官方把”凭证寿命”当成了需要预留操作时间的量,而不是临终提醒。
Agent SDK 月度独立额度。2026-06-15 起,订阅计划上通过 claude setup-token 生成的 1 年期 OAuth 令牌,以及 claude -p / Agent SDK 的非交互式使用,从独立的月度 Agent SDK 额度中扣除——与交互式使用额度完全分离。这意味着 CI/CD 管道和自动化工作流不再消耗日常交互式配额,对 DevOps 用户是一个关键的计费模型改进。
buildAuthUrl 函数构建授权 URL,支持多种登录方式(标准登录、SSO、Magic Link、Google)和组织级别的认证。
14.3 多云适配
企业用户可能不直接使用 Anthropic API,而是通过云平台的中间层访问 Claude 模型。Claude Code 支持三大云平台:
术语变更(2026-09-11):Google 侧的 Vertex AI 已更名为 Google Cloud’s Agent Platform,官方文档(含 IAM 与各云平台页面)已统一使用新名。本书下文除引用旧环境变量名(
CLAUDE_CODE_USE_VERTEX)外,一律改用新名。环境变量名本身未变——CLAUDE_CODE_USE_VERTEX仍是启用开关,改名只发生在产品命名层。
| 平台 | 环境变量 | 认证方式 | 特色 |
|---|---|---|---|
| AWS Bedrock | CLAUDE_CODE_USE_BEDROCK=1 | STS 临时凭证 | 跨区域推理 + Mantle 端点 + Auto Mode(Opus 4.7/4.8,2026-06-16) |
| Google Cloud’s Agent Platform(原 Vertex AI) | CLAUDE_CODE_USE_VERTEX=1 | ADC 凭证 | 元数据服务器 + Auto Mode(Opus 4.7/4.8,2026-06-16) |
| Microsoft Foundry(原 Azure Foundry) | CLAUDE_CODE_USE_FOUNDRY=1 | AD Token / API Key | 1M 上下文 + Auto Mode(Opus 4.7/4.8,2026-06-16) |
Vertex 侧的环境变量。除 ADC 之外,官方还列出 ANTHROPIC_VERTEX_BASE_URL 与 ANTHROPIC_VERTEX_PROJECT_ID——前者覆盖 Vertex 端点 URL,后者指定项目 ID。原稿只讲 ADC,未收这两项。
平台切换通过 getAPIProvider() 函数实现,优先级为 Bedrock > Vertex > Foundry > firstParty。
模型标识符映射
各平台使用不同的模型标识符,通过 ModelConfig 类型统一管理:
📌 本表快照于 Claude Code v2.1.285(2026-09-29)。这张表在 2026-09-11 手工修过一次(
opus-4-6 → opus-5),18 天后再次漂移(Opus 5.5 于 v2.1.280 / 09-22 成为默认 Opus,Sonnet 5.5 于 v2.1.284 / 09-28 成为 Anthropic API 上的默认 Sonnet)。凡这类枚举表,标快照版本比逐次追更划算——读者看到的数字若是半年前的,至少知道该自己核,而不是照抄。
这张表现在有远程通道了(v2.1.311)。 Bedrock / Mantle / Vertex / Foundry 上的模型设置改由 downloads.claude.ai 的签名文件下发,CLAUDE_CODE_MODEL_CATALOG=off 退出——快照口径从「本地版本决定」变为「本地版本 + 远程目录决定」。也就是说读者 /model 看到的清单不再只由装了哪个版本决定,官方可以在不改客户端的情况下调整模型目录;而签名文件是三条远程配置通道(System Prompt、定价遥测、模型目录——见 13.6.2)中唯一带完整性校验的。同版还把对模型无实际作用的 [1m] 后缀及其标签从模型名与 ID 中去除(后缀仍被接受)。
未识别的模型名也有了独立的降级路径(v2.1.312):自定义部署名、inference profile ARN 这类 Claude Code 不认识的名字(即使它们背后是 Sonnet 或 Haiku),改用短系统提示,CLAUDE_CODE_SIMPLE_SYSTEM_PROMPT=0 保留完整版;flagged 之后的自动切模型也覆盖未识别名,CLAUDE_CODE_DISABLE_REFUSAL_FALLBACK=1 可关闭。两个新开关(MODEL_CATALOG=off 与 SIMPLE_SYSTEM_PROMPT=0)构成一对逃生门:一个退掉远程目录,一个退掉降级提示——「新能力先上、退路以环境变量形式提供」的又一实例。
// 快照于 v2.1.285(2026-09-29)
const CLAUDE_OPUS_5_5_CONFIG = {
firstParty: 'claude-opus-5-5',
bedrock: 'us.anthropic.claude-opus-5-5',
vertex: 'claude-opus-5-5',
foundry: 'claude-opus-4-8',
};
const CLAUDE_SONNET_5_5_CONFIG = {
firstParty: 'claude-sonnet-5-5',
bedrock: 'us.anthropic.claude-sonnet-5-5',
vertex: 'claude-sonnet-5-5',
foundry: 'claude-sonnet-5',
};
⚠️ Foundry 那一行为什么没跟着改成 5.5。官方
microsoft-foundry页面在本表快照时点名的仍是claude-opus-4-8与claude-sonnet-5,没有 5.5。Bedrock 侧官方明确写「Primary model:Opus 5.5,例如us-*区域下为us.anthropic.claude-opus-5-5」,Vertex 侧写「Primary model:claude-opus-5-5」。三个云的代次并不同步,把 Foundry 一并「同步」成 5.5 是我按提案字面执行前回源挡下来的一处——代次落后本身就是事实,不该抹平。另有一条容易被「默认模型」这个词带偏的:Bedrock 与 Vertex 的 small/fast 模型默认仍是 Sonnet 4.5(如
us.anthropic.claude-sonnet-4-5-20250929-v1:0、claude-sonnet-4-5@20250929),不是 Sonnet 5.5。会话标题生成这类后台任务走的是这一档。模型 ID 随版本变化,请以
/model选择器实际列出的为准。同一批官方示例中还出现的 ID:Bedrock 侧有
us.anthropic.claude-opus-5、eu.anthropic.claude-opus-5、global.anthropic.claude-opus-5、us.anthropic.claude-opus-4-8、us.anthropic.claude-sonnet-4-6、claude-haiku-4-5-20251001-v1;Vertex 侧用@加日期后缀,如claude-sonnet-4-5@20250929、claude-haiku-4-5@20251001。注意两侧命名规则不同:Bedrock 是点分前缀 + 可选区域,Vertex 是日期后缀。
Bedrock 还支持跨区域推理,通过模型 ID 前缀指定区域:us.anthropic.*(美洲)、eu.anthropic.*(欧洲)、apac.anthropic.*(亚太)、global.anthropic.*(全局路由)。
Bedrock Service Tier。v2.1.122 新增 ANTHROPIC_BEDROCK_SERVICE_TIER 环境变量,支持选择 Bedrock 服务层级:
| 层级 | 说明 | 适用场景 |
|---|---|---|
default | 标准服务 | 通用场景 |
flex | 弹性容量,成本更低 | 非延迟敏感的批处理 |
priority | 优先调度,延迟最低 | 生产关键路径 |
Service Tier 通过 X-Amzn-Bedrock-Service-Tier HTTP Header 发送,为企业用户提供了延迟与成本之间的精细控制。
provider 白名单:allowedProviders
前面所有内容回答的都是「怎么连上某个云」。v2.1.285 新增的 allowedProviders 回答的是另一个问题:这台机器被允许连哪些 provider。
它是 managed setting——写在 policy 文件里,开发者无法从自己的 config 放宽。可枚举的取值共 8 个:Anthropic API、custom endpoint、Bedrock、Mantle、Vertex AI、Foundry、Claude Platform on AWS、Cloud gateway。白名单之外一律拒绝。
这一条把本章的讨论从「认证」推进了一层。此前 14.1 的 7 级令牌源优先级隐含的前提是:只要拿到正确类型的凭证,链路就该通。加上 allowedProviders 之后,前提变成:凭证正确 ≠ 这个 provider 可用。管理员可以在凭证完全合法的情况下,把 Bedrock 从一台机器的可选范围里划掉,此时 CLAUDE_CODE_USE_BEDROCK=1 不是「不生效」,而是被策略拒绝。
它与 14.1 那两条托管登录策略(forceLoginMethod / forceLoginOrgUUID)构成同一组治理手段:前者管「你必须用哪种登录方式」,后者管「你能用哪个 provider」。两者都位于用户配置之上,也都由管理员而非开发者决定。
allowedProviders 会自伤:白名单的拒绝面包含它自己的投放对象。 v2.1.296 修了一条值得单独记的 bug:一个下发 allowedProviders 且取值含 "gateway" 的 Claude apps gateway,会把在用户设置里指名了这个 gateway 的笔记本判定为不允许,从而锁在外面——策略把”连向自己”这条路也一并拒了。
这条的教训比 bug 本身宽:收紧一个集合时,往往会连带删掉你正依赖的那个入口。 它与 14.3.0 Mantle 那条是同型的——在那里,“列出 anthropic.claude-haiku-4-5 会把裸 haiku 别名从选择器移除”。两次都发生在”把允许清单写具体”这个动作上,而两次的受害者都是写下清单的人自己。
对配置 allowedProviders 的读者,可操作的含义是:必须把”gateway 自身下发的取值”与”客户端指向哪里”一起考虑,不能只列”我想允许的云”。⚠️ 官方 allowedProviders 的 8 个取值本轮未重新抓取,本章维持原有清单。
第二例自伤出现了(v2.1.318),教训随之升格。 该版修复:同一台机器上另一个登录存下的 allowedProviders 列表,会把当前会话在启动时整个拒掉。与 v2.1.296 那例合起来看,两例暴露的是两个不同维度的问题——296 是值域问题(取值集合没算上 gateway 自己),318 是状态隔离问题(列表按登录存储、拒绝判定却按机器生效)。第二次发生说明这不是偶发 bug 而是 allowedProviders 的结构属性:这台机器上任何一个登录都可能替你决定 provider 边界。 排障口诀相应升级——配置时要同时问两句:「允许了谁」和「这台机器上还有谁存过列表」;遇到”没配却被拒”,先排查其他登录的遗留状态。
14.3.0 Bedrock Mantle 端点
Mantle 是一个 Amazon Bedrock 端点,但它以原生 Anthropic API 形状服务 Claude 模型,而非 Bedrock Invoke API 形状。 它复用同一套 AWS 凭证、IAM 权限和 awsAuthRefresh 配置——认证侧没有任何新东西,变的是请求/响应的 API 形状。
| 维度 | 说明 |
|---|---|
| 开启 | CLAUDE_CODE_USE_MANTLE=1(或 true);/status 的 provider 行显示 Amazon Bedrock (Mantle) |
| 模型 ID | 前缀 anthropic.、无版本后缀,如 anthropic.claude-sonnet-5、anthropic.claude-haiku-4-5 |
| 可用模型 | 取决于组织被授予的权限,额外 ID 见 AWS 的 onboarding 材料 |
| 环境变量 | CLAUDE_CODE_USE_MANTLE、ANTHROPIC_BEDROCK_MANTLE_BASE_URL(覆盖默认端点 URL) |
可与 Invoke API 并行。Mantle 上的可用模型未必覆盖你当前在用的全部模型。把 CLAUDE_CODE_USE_BEDROCK 与 CLAUDE_CODE_USE_MANTLE 一并设置,即可在同一会话里调用两个端点:符合 Mantle 格式的 ID 走 Mantle,其余走 Invoke API,此时 /status 显示 Amazon Bedrock + Amazon Bedrock (Mantle)。
想在 /model 选择器里露出 Mantle 模型,需把其 ID 列进 availableModels。⚠️ 这里有个反直觉的坑:列出 anthropic.claude-haiku-4-5 会把裸 haiku 别名从选择器中移除——两个条目指向同一模型族,合并时只保留更具体的那个。要保留可选项,须一并列出想留的版本前缀或完整 ID。
从本书视角看,Mantle 的意义在于:它是”多云认证层”向”统一 API 形状”收敛的信号。 云厂商的差异被压缩到端点选择与 ID 命名规则,认证侧仍是同一条 AWS 凭证链。这与 14.5 教训二”多云不再是劣化版”的论点方向一致,只是收敛发生在 API 形状而非功能清单上。
服务端视角:gateway 侧的 Mantle 与两项 Bedrock upstream 配置。上面讲的是客户端直连 Mantle。若部署形态是 Claude apps gateway 居中,同一件事落在 upstream 配置上:
| 版本 | 项 | 内容 |
|---|---|---|
| v2.1.283(09-25) | mantle upstream provider | gateway 新增 Mantle 端点作为 Bedrock 的 upstream 选项 |
| v2.1.281(09-23) | assume_role | gateway 经 STS 承担一个 IAM 角色再调 Bedrock,可跨 AWS 账号,可选每位开发者一个会话 |
| v2.1.281(09-23) | guardrail: {id, version} | 对该 upstream 的每个请求施加 Amazon Bedrock guardrail;要求所有 Bedrock upstream 要么都设要么都不设 |
| v2.1.295(10-08) | models 列表 | 每个 upstream 可声明只接收哪些模型:仅列出的模型会被发往该 upstream,failover 时同样生效;一个条目里可用一个 * 作通配 |
| v2.1.295(10-08) | timeouts.upstream_ttfb_ms | 限制 Bedrock / Vertex / Foundry 及其他云 upstream 的流式响应首字节时间;超时后 failover 或返回 502 |
| v2.1.314(10-30) | groups | upstream 按 IdP 分组路由:只服务所列 IdP 组的开发者,failover 同样生效 |
| v2.1.314 / 316(10-30/31) | guardrail_trace / guardrail.input_tagging | guardrail_trace 记录哪个 filter 命中;input_tagging 为 Bedrock guardrail 的 prompt attacks filter 包输入标签,all_messages_and_system 连系统提示一起打 |
| v2.1.318(11-04) | assume_role on mantle | assume_role 扩展到 mantle upstream——跨 AWS 账号承担角色 + 按开发者做 AWS 成本归因 |
新增的两行把 upstream 配置的语义从「能连到哪」扩展到了另外两维:哪些模型走这条路(models)与多久算连不上(TTFB)。
models 这一条尤其值得与客户端对照着看:限制模型路由这件事现在同时存在于两个地方——客户端的 availableModels 与网关 upstream 的 models。两者语义并不相同:前者管”这台机器能看到/能选哪些模型”,后者管”哪些模型会被转发到这个上游”,且后者在 failover 路径上同样生效。排障时先要分清是哪一侧挡的,否则会在客户端设置里反复排查一个网关侧的问题。
⚠️ 两者同时设置时的优先级官方未明示,本书不作推测——这是本章目前唯一一处明确留白的配置交互。
同版本还补了两个可观测性字段:upstream_request_id(审计字段,记录 Bedrock / Anthropic API 等上游的 request id)与 request-id 响应头,让 Claude Code 遥测里的 request_id 能与 gateway 审计日志对齐。对本章的主题来说这是正向材料:过去”客户端看到的失败”与”网关记录的失败”难以对应,现在有了共同键。
assume_role 与 14.3.1 的 WIF 是同源主题的不同落点:WIF 让客户端凭身份换短效令牌,assume_role 让网关凭身份承担角色——思路都是「用身份换凭证,而不是存凭证」,差别只在执行者是客户端还是网关。「每位开发者一个会话」这个可选项尤其值得注意:它把角色承担粒度从「一个网关一个身份」细化到「一个人一个会话」,代价是 STS 调用次数与可观测性复杂度。v2.1.318 把它扩展到 mantle upstream 时,官方点明了第二个用途:按开发者做 AWS 成本归因——「每人一会话」从可观测性代价变成了计费粒度收益,角色承担粒度直接决定账单粒度。这与 13 章 modelPricing.multiplier 形成「能力治理 vs 成本治理分家」的对照:模型能不能用归策略管,用了记在谁头上归身份管。
guardrail 的「要么都设要么都不设」是一条容易踩的硬约束:它不是逐 upstream 的开关,混设会被拒。
Bedrock 上的 1M 上下文
Claude Sonnet 5、Opus 4.6 及之后、Sonnet 4.6 在 Amazon Bedrock 上支持 1M token 上下文窗口。其中有一条容易踩空的细节:Sonnet 5 在 Invoke API 与 Mantle 端点上始终以 1M 运行,没有 [1m] 变体可选;其他模型则在 Invoke API 上选择 1M 变体时由 Claude Code 自动启用扩展上下文窗口。
换句话说,“选一个
[1m]后缀的模型 ID”这个操作对 Sonnet 5 不成立——它没有可选项。读者若照其他模型的习惯去找claude-sonnet-5[1m],会找不到。
自建网关这条路径此前完全没写。v2.1.285 起,走自定义 ANTHROPIC_BASE_URL 的会话同样会用上模型自带的 1M 上下文窗口(适用 Opus 4.7+、Sonnet 5+、Fable)。官方给的兜底动作是:若你的网关在 200K 处截断,执行 /autocompact 200k。
失败侧此前没写:上游拒绝 1M 时不是报错,是静默降级。 上面讲的是”哪些形态下会拿到 1M”,v2.1.295 补的是另一半:当 gateway / Bedrock / Vertex / Foundry 拒绝 1M 变体时,Claude Code 现在去掉 [1m] 后缀重新发送,而不是整体失败。
实践含义很直接:“我配了 1M 但好像没生效”很可能不是配置错误,而是上游拒绝后客户端静默降到了 200K。 这条与 14.4 那条”管理员移除默认模型时改为静默切到同层级旧可用模型”是同型行为。
本章至此已经出现三处静默降级——模型可用性降级(切旧模型)、1M 降级(去 [1m] 后缀)、以及 v2.1.302 修的”会话中途切换云厂商”之前的失败形态。可以抽成一条可复用的排障规则:这条链路上的失败大多以「降级」而非「报错」呈现。 因此”我以为的配置”与”实际生效的配置”之间的偏差不会触发任何告警,只能靠 /status 之类的显式观测手段去核对。
这条规律不是自然达成的,是持续修补的产物。 2026 年 10–11 月的三条修复,修的全是「该降级却报错」的偏差:① sonnet / opus / haiku 别名在 Vertex / Bedrock 上新模型不可用时,原本中途报错而非切旧模型(v2.1.316);② Foundry 资源缺默认模型部署时,现在回退到同家族旧模型(v2.1.314);③ LLM gateway 对服务端安全检查回 403/422 时,auto mode 原本每轮失败(v2.1.317)。第二条同时补齐了 14.4 降级矩阵缺的第三朵云——三大云对「默认模型不可用」的行为自 2.1.314/316 起对齐为「切同家族旧模型」。三例合读的正确姿势:降级优先不是架构的默认属性,而是官方在逐云、逐场景追平的行为基线——每一轮「该降级却报错」的修复,都在提醒你上一个版本可能刚好在这个场景上以报错开场。
这一条的位置比看上去重要。上面讲 Bedrock 的 1M 覆盖的是「云厂商托管」形态,而企业里更常见的出口是自建网关 + WIF 统一出网——即 14.3.1 那条链路。此前这类部署会安静地停在 200K,且没有任何报错提示窗口被截断;现在窗口与直连对齐,剩下的变量只有网关自己肯不肯放那么长。
源码引用:多云认证参见 bedrock.ts,模型配置参见 configs.ts,API 提供商选择参见 providers.ts。
14.3.1 Workload Identity Federation
2026 年 5 月,Anthropic 为 Claude API 引入了 Workload Identity Federation(WIF)——这是认证架构的根本性变革,从”持有静态凭证”转向”证明身份获取临时令牌”。
三要素架构
| 要素 | 标识符前缀 | 作用 |
|---|---|---|
| Service Account | svac_ | 定义身份主体(“谁在请求”) |
| Federation Issuer | fdis_ | 定义信任的 IdP(“谁签发的身份”) |
| Federation Rule | fdrl_ | 定义映射规则(“IdP 身份如何映射到 Anthropic 身份”) |
令牌交换流程
WIF 基于 RFC 7523 jwt-bearer grant:
1. 工作负载从 IdP 获取 OIDC JWT
(来源:AWS IAM / GCP ADC / Azure IMDS /
GitHub Actions / Kubernetes / SPIFFE/SPIRE)
2. 用 OIDC JWT 换取 Anthropic 短效访问令牌
(sk-ant-oat01-...)
3. SDK 自动处理令牌交换和刷新
双层刷新策略
| 刷新层 | 触发条件 | 目的 |
|---|---|---|
| Advisory | 令牌过期前 120 秒 | 提前刷新,避免请求中断 |
| Mandatory | 令牌过期前 30 秒 | 强制刷新,确保不使用过期令牌 |
令牌有效期约束:Anthropic 令牌有效期 = min(rule.ttl, 2 × 剩余 IdP JWT 有效期)。这保证了 Anthropic 令牌永远不会长于上游身份的有效期——安全性的核心保证。
支持的 IdP
AWS IAM Identity Center、GCP Application Default Credentials、Azure Instance Metadata Service、GitHub Actions OIDC、Kubernetes Service Account Token、SPIFFE/SPIRE SVID。
JWKS 源配置模式。Anthropic 官方 WIF 文档明确了三种 JWKS(JSON Web Key Set)源配置方式:
| 模式 | 配置方式 | 适用场景 |
|---|---|---|
| discovery(默认) | 通过 /.well-known/openid-configuration 自动发现 JWKS 端点 | 公网可达的标准 IdP(AWS、GCP、Azure) |
| explicit_url | 直接指定 JWKS 端点 URL | IdP 支持 OIDC 但发现端点不可用 |
| inline | 上传密钥集(JSON Web Key Set 内联) | 私有 Kubernetes 集群等不可从公网访问的签发者 |
URL 约束:所有 JWKS 端点必须使用 HTTPS 协议、端口 443、公网 DNS 解析的域名。这对于私有 Kubernetes 集群部署场景(需使用 inline 模式绕过公网访问限制)尤其重要。
GCP X.509 证书型 WIF:v2.1.121+ 扩展了 GCP 的 WIF 支持——除了默认的 ADC metadata server 方式,还支持 X.509 证书型 Workload Identity Federation。通过将 GOOGLE_APPLICATION_CREDENTIALS 设为凭证配置文件路径即可启用,为 GCP 上的 WIF 提供了更灵活的认证路径。
gateway 侧的身份映射也多了一个可配置维度(v2.1.312)。 JWKS 三模式之后,gateway 新增 oidc.user_id_claim:当 IdP 的 sub 不适合做人员标识时(典型如 Microsoft Entra ID 用 oid),可改按其他 id_token claim 识别人。这是身份映射层从「信任谁签发」到「怎么读出谁」的细化——WIF 讲的是网关怎么验 IdP 的签名,这一条讲的是验完之后拿哪个字段当人名。
配套的三条说明 gateway 的身份层正在向按人记账收敛:GET /v1/organizations/analytics/cost 成本报表 API(v2.1.317,支持按日 / 按开发者 / 按 IdP 组读历史消费);admin.identity_retention_days(v2.1.317,开发者-IdP 组关系的每日快照保留天数,成本报表正是按它分组);federation external_account credentials file 的 Google access token 到期告警(v2.1.318)。身份不再只是认证的中间量,而是账单与审计的主键。
WIF/profile 凭证在优先级链中的位置
本节前面的技术细节(三要素、RFC 7523、双层刷新、JWKS 三模式)回答的是”WIF 怎么工作”,但没有回答”WIF 凭证在优先级链里站哪一位”——而这恰恰是排查问题时最先需要的。
答案是:profile 与 federation 凭证占 14.1 优先级表的第 6 级,即排在 /login 订阅凭证之前。Claude Code 按下表顺序检查三个来源,命中第一个已设置的即停止:
| 来源 | 由什么设置 | 相对 /login 的排位 |
|---|---|---|
| Named profile | ANTHROPIC_PROFILE | 之上——不论该 profile 是哪种 auth mode |
| Federation variables | ANTHROPIC_FEDERATION_RULE_ID 与 ANTHROPIC_ORGANIZATION_ID 两个都设置 | 之上 |
| Active profile | 配置目录中的 active_config 文件,或名为 default 的 profile | auth mode 为 oidc_federation 时之上;为 user_oauth 时排在可用的 /login 凭证之下 |
最后一条的 user_oauth 例外不是随意定的。官方给出的设计意图是:防止一个残留的 ant auth login profile 把你已用 /login 登录的账号的请求挪走。排序规则在这里保护的是”用户显式做过的事”(/login)优先于”某次 CLI 操作留下的痕迹”。
边界条件:Claude Code 在 bare mode、Claude Desktop、cloud sessions 中不读取 profile 或 federation 变量,这些会话的 /status 不显示 Profile 行。
这个边界要分成强度不同的两档,此前被合并成了一句。
第一档:只影响第 6 级。 上句所述——bare mode / Desktop / cloud sessions 不读 profile 与 federation 变量。
第二档:整条 7 级链都不适用。 官方原话:“Cloud sessions always use your subscription credentials. If you set ANTHROPIC_API_KEY or ANTHROPIC_AUTH_TOKEN in the cloud environment, it doesn’t override your subscription credentials.” 也就是说,在云端会话里前 5 级(云凭证变量、bearer token、API key、apiKeyHelper、setup-token)全部被订阅凭证压过,不是”第 6 级不适用”这一件小事。
官方还有一条把第一档推得更远:“Claude Desktop and cloud sessions do not call apiKeyHelper or read these environment variables: they use OAuth”——Desktop 与 cloud sessions 连第 4 级(apiKeyHelper)与第 2/3 级(两个环境变量)都不走,只有运行第三方推理配置的桌面会话例外。
一句话结论:14.1 那张 7 级优先级表在云端会话里整体不作数。 这与”provider selection 高于一切”是同型的另一套规则——本章的价值也因此更清楚:那张表描述的是本地 CLI 会话,把它当成全环境通则会得出完全错误的排障方向。
令牌交换还会读别的变量。 除本章已记的 ANTHROPIC_FEDERATION_RULE_ID 与 ANTHROPIC_ORGANIZATION_ID 外,令牌交换时还会读取 ANTHROPIC_IDENTITY_TOKEN_FILE 等 WIF 参考中的变量(官方 WIF 参考已迁至 platform.claude.com,本章引用时按新址核)。另有一条错误形态值得登记:user_oauth profile 登录过期且无法续期时,会产生专门的 expired profile login 错误,而不是通用认证失败——排障时看到这个串可以直接定位到 profile 续期,不必去查凭证本身。
「会话中途切换云厂商」是一条此前未写的路径。 14.3 讲的平台切换由 getAPIProvider() 实现、优先级为 Bedrock > Vertex > Foundry > firstParty——那段描述的是启动时的选择。v2.1.302 修了一条此前没有对应描述的失败:“diagnostics: Extra inputs are not permitted”——会话运行中切到 Vertex 或 Bedrock 后请求失败。
这是本章第一次出现”运行中切换”的证据,它说明启动选择与运行中切换是两条不同的路径,前者有明确的优先级规则,后者此前连失败形态都没有被记录过。⚠️ 官方只给了错误串、未给机制(哪些参数组合触发、是否只影响中途切换),本书不作外推。
怎么确认选中了哪个来源:运行 /status,有 Profile 行时它会取代 Login method 行;profile 生效时 Organization 与 Email 行显示该 profile 的账号。带 --debug 启动还会在 ~/.claude/debug/<session-id>.txt 写入 Using Anthropic profile auth 行;若因存在可用的 /login 凭证而跳过了 user_oauth active profile,调试日志会写明改用 claude.ai 登录。
计费归属首次有了启动时的显式披露(v2.1.319)。 当 claude.ai 登录结束、Claude Code 继续用 ant auth login 的登录凭证运行时,启动会警告并点名正在计费的 Claude Console 组织。这与 user_oauth 例外保护的设计意图一脉相承——账单跟人走,但此前用户看不见跟到哪:切换凭证后到底在给哪个组织烧额度,现在至少启动时会被告知一次。对多组织用户的排障价值很直接:用量对不上账时,先看这条警告有没有出现。
14.4 凭证缓存、模型可用性与错误处理
本节原有内容只覆盖凭证这一条链路。v2.1.281–2.1.285 的几处改动指向了平行的另一条:模型可用性。它们是两件不同的事,各有各的 TTL,各有各的失效模式。
各平台的凭证都有缓存机制,AWS STS 凭证缓存 TTL 为 1 小时,GCP ADC 凭证也是 1 小时。缓存通过 memoizeWithTTLAsync 实现。
认证错误的统一处理:
| 平台 | 错误检测 | 恢复策略 |
|---|---|---|
| Bedrock | CredentialsProviderError / 403 | 清除缓存 → 重新认证 |
| Vertex | Google 认证库错误 / 401 | 清除缓存 → ADC 刷新 |
| Foundry | Azure AD 错误 | 重新获取 Token |
自动凭证刷新。Claude Code 新增 awsAuthRefresh 和 gcpAuthRefresh 设置——当检测到凭证过期时,自动运行刷新命令(如 aws sso login 或 gcloud auth application-default login),并流式输出以便用户完成浏览器认证流程。awsCredentialExport 设置则支持 aws sts assume-role 场景的凭证导出。这将”清除缓存→重新认证”的手动策略升级为”自动检测过期→自动刷新→无感恢复”的自动化流程。
✅ 「待验证」标注已摘除(2026-09-11):
awsAuthRefresh、awsCredentialExport、gcpAuthRefresh三项现已在官方settings-reference中各有独立条目,属官方确认。原稿自标的「来自第三方文档站点,非官方」⚠️ 已删除。补充一项当时未记的区分:
awsAuthRefresh用于刷新流程写入.aws的场景,awsCredentialExport用于刷新流程打印凭证的场景(如aws sts assume-role)——两者不是替代关系,而是对应不同的刷新命令输出方式。
模型可用性:第二条链路
凭证有效 ≠ 模型可用。 下面三条都发生在「认证已经成功之后」,属于 v2.1.285:
| 机制 | 行为 |
|---|---|
| 降级 | Bedrock / Vertex AI 会话在管理员移除默认模型访问时,改为切到同层级的旧可用模型,不再直接失败;会话标题与摘要随之回退 |
| 可用性缓存 | Bedrock / Vertex 的启动模型检查,账户不可用的模型记住最长 1 天,不再每次启动都重查 |
| 签名修正 | Bedrock / Mantle / Claude Platform on AWS 请求打到非默认端口的 base URL 时,SigV4 签名的 Host 头现在包含端口 |
同版本还把 Bedrock、Vertex、Mantle 的启动模型检查改为与其它请求一样带上 User-Agent / x-app / session ID 头,并标识自己为 Claude Code。
这条链路不只是”TTL 会带来延迟”,它自身会算错(v2.1.287)。 上面三条讲的是机制,还有两条讲的是检查本身的正确性:
| 修复 | 内容 |
|---|---|
| 忽略生效策略 | 启动时的模型可用性检查此前会忽略强制生效的 availableModels,后果是 /model 选择器可能被压成只剩一行 Opus |
| 探测身份不一致 | 在 CLAUDE_CODE_SKIP_*_AUTH 下,当 ANTHROPIC_CUSTOM_HEADERS 重复设置 Authorization 时,可用性检查发出的 Authorization 头与真实请求不同 |
第一条的后果是检查结果与实际允许范围不一致——/model 里显示的东西不是你能用的东西。第二条更值得记:它意味着用 A 身份探测、用 B 身份请求,探测结果在原理上就不可信。
这与本书反复出现的”计量会出错”是同一条规则在认证侧的版本:不要把探测结果当成事实,先确认探测本身用的是什么身份、有没有纳入生效策略。
⚠️ 提案原文把改用同类请求头的三家写成了「Bedrock / Mantle / Claude Platform on AWS」,其中第三家应为 Vertex。官方 changelog v2.1.285 的两条是分开的:一条是 SigV4 Host 头含端口(Bedrock / Mantle / Claude Platform on AWS),另一条是启动模型检查带头(Bedrock / Vertex / Mantle)。按提案合并写会把两个不同的集合混成一个。
降级那条值得单独看一眼。「管理员撤掉默认模型」在组织里是常规操作——换代次、控成本、收权限都可能触发。旧行为是直接失败,用户看到的是认证类报错,排查方向被误导到凭证上;新行为是静默换模型,代价是会话标题与摘要也在同一时刻回退,用户看到的是「自己在用的模型变了」而没有提示。可用性缓存最长 1 天进一步拉长了感知延迟:上午刚被撤掉的模型访问权,下午恢复了,但若 Claude Code 已缓存「不可用」,要等缓存过期才重新检查。
凭证机制的四类负向边界
上面写了「有这个机制」,官方随后补的是「这个机制怎么漏」:
- 进程残留(v2.1.281):
gcpAuthRefresh/awsAuthRefresh的登录进程在 Claude Code 退出或刷新超时后仍在运行,Windows 上还占着 localhost 回调端口。占着回调端口意味着下一次登录可能起不来——这是「自动化刷新」引入的新失效模式,手动刷新时不存在。 - 钥匙串锁定(v2.1.281):macOS 上写入凭证时若登录钥匙串处于锁定状态(例如刚从睡眠唤醒),会丢掉已存的 MCP OAuth token 或删掉钥匙串条目。这把「凭证存储」的可靠性挂在了操作系统的锁状态上。
- 多会话竞态(v2.1.285):两个会话争抢恢复同一个崩溃进程留下的 login refresh lock 时,会出现罕见认证失败。本章 14.1 的优先级链与 14.4 的刷新流程都隐含单会话假设,这条是该假设的边界。
三条合起来指向同一件事:自动刷新把凭证管理从「用户动作」变成「后台进程」,于是进程生命周期、OS 锁状态、跨会话并发这三类原本与认证无关的问题,全都变成了认证问题。
-
凭证越界(credential bleed,v2.1.299):当
ANTHROPIC_BASE_URL指向第三方 gateway 时,feature flag、启动、fast mode、profile、feedback 这几类本应发往 Anthropic 的请求,错误地带上了为该 gateway 配置的 API key;托管设置请求在ANTHROPIC_BASE_URL由托管设置文件设置时同样如此。这一条与前两条性质都不同:前两条是”凭证没拿到”,这一条是”凭证拿到了但用错了地方”。 而且它只在本章主讲的自建网关形态下发生——用户的心智模型是”改了 base URL 就把所有流量导向网关”,实际上那五类旁路请求仍去 Anthropic,只是带着网关的 key。
这里有一条值得单独记住的边界:
ANTHROPIC_BASE_URL改的是模型请求的去向,不是所有出站请求的去向。 官方修复的措辞保留了 “Anthropic API keys are still sent” 这半句——即正常的 Anthropic 侧请求仍在发自己的 key,被修的只是”该发 Anthropic key 的请求错带了 gateway key”那一部分。 -
成功信号会说谎(v2.1.290):macOS 上若钥匙串拒绝写入新登录且无法删除旧条目,
/login仍会报告成功——用户以为换好了账号,实际仍在用旧凭证。同版本还修了已有凭证时首次启动仍要求选择登录方式的问题。这一条是四类里最危险的:前三类是”机制会漏”,这一类是”可见结果与实际状态不一致”。 静默失败至少还会表现为”接下来用不了”,从而触发一次排查;报成功则不触发任何排查动线——用户会带着错误的前提继续工作很久。它直接接到 14.5 教训五”认证不等于安全”。
四类合起来可以排成一个递进:拿不到(进程残留 / 钥匙串锁定)→ 拿不稳(多会话竞态)→ 拿错了地方(凭证越界)→ 以为拿到了(成功信号说谎)。 越往后越难发现,因为越往后外部表现越正常。
14.5 多云适配给 Agent 产品的教训
OAuth PKCE 和多云认证的技术细节在文档中都能找到,但 Claude Code 的实现揭示了几个不那么显而易见的教训:
教训一:认证是用户流失的第一道坎
如果用户需要手动配置 API Key、手动刷新 Token、手动切换云平台——他们会在第一步就放弃。Claude Code 的多级令牌源自动探测(云平台凭证 → Gateway Session → 环境变量 → OAuth 令牌)说明 Anthropic 在认证体验上投入了大量工程:用户不应该”配置”认证,认证应该”自动发生”。
教训二:多云不是三个 if-else
Bedrock、Vertex、Foundry 三个平台的差异不只是 endpoint 不同——它们的认证方式、模型标识符、区域策略、错误码格式都不同。ModelConfig 类型用统一的数据结构屏蔽了这些差异,上层代码完全不需要知道底层用的是哪个平台。
但更关键的是优先级策略(Bedrock > Vertex > Foundry > firstParty)——当用户同时设置了多个平台环境变量时,系统需要有确定性的选择逻辑而不是报错。
云平台功能对齐:2026-06-16,Auto Mode(后台安全检查替代逐次权限确认)从 Anthropic 直连扩展到 Bedrock、Vertex、Foundry 三大云平台(仅限 Opus 4.7/4.8)。2026 年 7 月进一步完善:Google Cloud(07-10)和 Azure(07-11)相继上线 Auto Mode GA——标志着 Auto Mode 在核心云平台达到生产就绪状态。多云部署不再是”劣化版”,而是功能几乎对等的选择。
⚠️ 启用方式已过时(与第 13 章 13.6.3 同步更正)。原稿写「启用方式:
CLAUDE_CODE_ENABLE_AUTO_MODE=1+ Shift+Tab 切换到 auto mode」。该 opt-in 在三大云平台上已被取消:自 v2.1.207(2026-07-11) 起,Bedrock、Google Cloud’s Agent Platform、Foundry 上的 Auto mode 不再需要CLAUDE_CODE_ENABLE_AUTO_MODE,管理员改用 settings 中的disableAutoMode(或permissions.disableAutoMode)关闭。这与上文的「Google Cloud 07-10 / Azure 07-11 上线 Auto Mode GA」实为同一批变更,可合并理解:GA 与取消 opt-in 是同一次发布动作的两面。旧写法在云平台上的实际后果是:读者设了环境变量却发现没变化(变量已无作用),或反过来以为必须设才能用(其实早已默认可用)。
Gateway 消费统管:v2.1.225(2026-08-07)新增 Gateway 控制台消费限额可视化——用户可直接在 Gateway 控制台查看消费限额和用量,覆盖 AWS + GCP + Azure 多云消费,为多云场景的统一计量计费提供 UI 层基础。同版本还引入跨机器会话消息传递功能,对 OAuth Token 同步和会话状态迁移提出新的技术需求。
auto mode 的分类器改走服务端。v2.1.278(09-19)起,Claude API 与企业用户,以及 Bedrock / Vertex / Foundry / 网关上的 auto mode 默认改用服务端分类器,不再收分类器开销;在这些平台上可用 CLAUDE_CODE_AUTO_MODE_SERVER=0 退出,回退到计费分类器时会告警,/status 里多一行 Auto mode server 显示本次会话跑在哪一侧。这是「多云不是三个 if-else」的又一实例:同一个功能在 Anthropic 直连与三大云上有不同的计费路径,退出开关也只在云侧存在。
教训三:凭证 TTL 与模型可用性 TTL 是两条独立的 TTL
AWS STS 凭证缓存 1 小时、MCP 认证失败缓存 15 分钟——这些 TTL 不是随便选的。太短会导致频繁认证请求(影响体验和被限流),太长会在凭证被撤销后仍然使用过期凭证(安全风险)。缓存 TTL 是安全策略的一部分,不是性能参数。
v2.1.285 之后还要补一句:模型可用性的缓存是另一条 TTL,最长 1 天(见 14.4)。两条 TTL 的语义并不相同——凭证 TTL 到期是「不确定还能不能用」,故必须重取;模型可用性 TTL 到期是「上次查到不能用」,故到期前会继续使用旧结论。管理员上午撤权限、下午恢复,用户在缓存期内仍然被降级到旧模型,且不会收到任何提示。把两类缓存放在同一个 TTL 框架下讨论,会漏掉这条不对称。
教训四:从凭证到身份
Workload Identity Federation 代表了一种范式转变——从”持有凭证即拥有权限”到”证明身份即获得临时凭证”。这对 Agent 产品意味着:Agent 不应存储长期 API Key,而应通过身份证明获取短期令牌。
WIF 的令牌有效期约束设计(不超过 2× 上游身份有效期)提供了一个安全最佳实践:即使在 Agent 的长运行会话中,任何时刻的有效凭证都有有限的生命周期。这与传统 API Key 的”永久有效直到手动撤销”形成了鲜明对比——静态 API Key 的时代正在结束。
教训五:认证不等于安全
2026 年 6 月,Claude Code 引入了文件系统级安全增强:在写入可执行配置文件(shell 启动文件如 .zshenv、git config、构建工具配置如 .npmrc/.bazelrc)前会主动提示——即使在 acceptEdits 模式下也不跳过。这意味着即使凭证验证通过,文件和命令安全性仍需独立保护。这是”最小权限”原则在文件系统层的延伸:凭证验证不等于文件安全,令牌有效不代表操作安全。
v2.1.281–2.1.285 的改动给这条教训又加了两层。
第一层,从凭证层推进到 provider 层。 14.1 的 7 级优先级回答的是「用哪个凭证」,allowedProviders(v2.1.285)回答的是「这台机器能用哪个 provider」。拿到合法凭证并不等于某个云可用——认证通过只是这条链上的第一关。
第二层,认证配置本身可以是攻击面。 v2.1.284 修复了 ANTHROPIC_FOUNDRY_RESOURCE 未经校验就被插值进 Foundry 端点主机名的问题;现在非纯资源名的值一律拒绝。这一条的性质与前面的「写可执行配置文件前提示」完全不同:那里防的是模型改你的配置,这里防的是配置值变成主机名的一部分。一个用于认证的普通环境变量,因为它参与构造了请求目标,就成了注入点——而且这类注入面在凭据体系里最难被意识到,因为它看起来只是「填了个资源名」。
14.6 设计启示
-
多云适配是企业级产品的必要条件。大企业不会为了用 Claude Code 而改变云战略。
-
统一的 API 抽象屏蔽底层差异。上层代码不需要知道底层用的是 Bedrock 还是 Vertex——
ModelConfig做了翻译。 -
凭证管理比看起来复杂得多。缓存、刷新、错误恢复、多平台——一个认证模块可能比想象中要重好几倍。