API 报 401 / 403 怎么排查?鉴权失败的九个原因

2026-08-06

401 和 403 是两回事:401 是「我不知道你是谁」,403 是「我知道你是谁,但你不能做这件事」。分清这一点,排查范围立刻缩小一半。

这篇按从简到繁的顺序列排查项。密钥本身的管理规范见 API Key 安全管理

先分清两个状态码

401 Unauthorized:鉴权信息缺失、格式错误、密钥无效或已失效。问题出在「身份」这一层。

403 Forbidden:身份认出来了,但这个身份没有权限做当前操作。可能是模型没开通、地域不允许、实名认证未完成、账户欠费被限制。

有些厂商的实现并不严格遵守这个区分,两种情况都返回同一个码。所以状态码只是第一线索,真正有用的是响应体里的错误信息——务必把它完整打印出来,别只记状态码。

401 的六个常见原因

一、请求头写错。 标准写法是 Authorization: Bearer <你的密钥>。常见错误:漏了 Bearer 前缀、Bearer 和密钥之间多了或少了空格、大小写写错。也有厂商用自定义头(比如某个专用的 key 头),照它文档写。

二、密钥里混进了空白字符。 从网页复制密钥时带上了换行或首尾空格,肉眼看不出来。写代码时 trim 一下,或者把密钥打印出来看长度对不对。

三、密钥存进环境变量时被引号包住了。.env 文件里写成带引号的形式,有些加载器会把引号一起读进去。检查方法是打印出来看开头结尾有没有引号。

四、用错了密钥类型。 有些平台区分「API 密钥」和「访问令牌」,或者区分不同产品线的密钥。控制台里生成的那一串未必是调用这个接口该用的。

五、密钥已被吊销或过期。 轮换后旧密钥失效、试用期密钥到期、误删重建。到控制台确认这把密钥当前是否有效。

六、请求打到了错误的服务地址。 地址不对时,对方压根不认识你的密钥。这一项常和 base_url 填错同时出现,见 OpenAI 兼容端点怎么填

403 的三类常见原因

一、模型或能力没开通。 很多平台的模型需要单独申请或开通,账户能调 A 模型不代表能调 B 模型。响应体通常会提示具体是哪个资源没权限。

二、账户状态限制。 实名认证未完成、余额不足、欠费停服、触发风控。这类问题在控制台首页一般有明显提示。

三、地域或网络限制。 服务只对特定地域开放,或者你的出口 IP 不在允许范围。企业环境里还可能是代理改写了请求头导致鉴权信息丢失。

一条稳定的定位顺序

按这个顺序走,多数问题三步内能定位。

第一步:用 curl 最小化复现。 抛开 SDK 和框架,直接用 curl 带上密钥请求一次。目的是把「代码问题」和「凭证问题」分开。curl 也失败 → 凭证或地址问题;curl 成功 SDK 失败 → 代码或配置问题。

第二步:打印实际发出的请求头。 注意是实际发出的,不是你写的那行代码。中间可能有拦截器、代理、框架默认配置改了头。打印时把密钥打码,只看格式和长度。

第三步:换一把新密钥试。 控制台新建一把,直接硬编码测一次(测完立刻删掉这行代码)。通了说明是旧密钥或配置读取的问题,不通说明是账户或权限层面的问题。

第四步:换一个模型试。 如果换成一个基础模型能通,说明原来那个模型没开通权限,属于 403 类问题。

几个容易忽略的场景

多环境配置串了。 开发、测试、生产用了不同的密钥和地址,配置加载顺序出错导致混用。排查时先确认程序真正读到的是哪份配置。

容器里没拿到环境变量。 本地跑得好好的,进容器就 401——十有八九是环境变量没注入进去。进容器里打印一下就知道。

CI 里的密钥没配。 流水线里跑的测试报 401,通常是仓库的密钥变量没设置或者分支保护规则限制了访问。

密钥被日志脱敏工具截断了。 少数情况下,脱敏中间件会把请求头里的敏感字段替换掉,导致发出去的头是残缺的。这个很隐蔽,怀疑时抓一次真实出站请求看。

从「能复现」到「能预防」

排查完一次之后,值得顺手做几件事,让同类问题不再重复出现。

一、把配置校验前置到启动时。 服务启动时就检查密钥是否存在、格式是否合理、能否调通一次最小请求。这样问题在部署阶段就暴露,而不是等第一个用户请求进来才报错。这一步的成本很低,收益很高。

二、给配置项加明确的错误提示。 密钥为空时,报「未配置 XXX 环境变量」,而不是让请求带着空密钥发出去然后收 401。前者一眼定位,后者要绕一圈。

三、区分环境的配置来源。 开发、测试、生产的密钥和地址分开管理,并在启动日志里打印当前使用的是哪个环境、哪个地址(密钥打码)。混用配置导致的 401 非常常见,而且极难靠猜排查。

四、把密钥轮换做成流程。 定期轮换是安全要求,但轮换恰恰是 401 的高发时刻。流程上要保证新旧密钥有重叠期,先加新的、确认生效、再撤旧的,而不是直接替换。见 API 密钥轮换

团队里最常见的三个场景

场景一:新同事第一次跑起来。 十有八九是环境变量没配或者配错了文件。解法是把配置模板和说明写进项目 README,并且启动时给出明确提示。

场景二:CI 里突然全红。 通常是仓库密钥过期、被轮换、或者分支保护规则改了导致拿不到变量。先看 CI 的环境变量配置页,别在代码里找。

场景三:容器化之后就不行了。 本地能跑、进容器就 401,基本都是环境变量没注入。进容器里打印一下环境变量(密钥打码)立刻能确认。

这三个场景占了团队内 401 报障的大多数,值得写进内部文档。

排查完之后做两件事

第一,把错误信息完整记进日志。 状态码 + 响应体 + 请求 ID(多数厂商会返回一个可用于工单的追踪 ID)。下次再出问题,有这三样能省一半时间。

第二,把鉴权错误从重试逻辑里剔除。 401/403 重试多少次都不会成功,只会白花时间。重试应该只对限流和服务端临时错误生效,见 API 重试与退避

三个高频问题

问:为什么同一把密钥有时通有时不通? 排查两个方向:一是多实例的配置不一致(有的实例读到了旧配置),二是走了不同的出口或代理,被地域策略拦了。

问:密钥泄漏了怎么办? 立刻到控制台吊销,再发新的,然后查用量有没有异常。轮换流程见密钥管理相关文章。

问:403 提示模型无权限,但控制台显示已开通? 常见于开通后需要一定时间生效,或者开通的是另一个地域/另一个产品线。等一会儿再试,仍不行就提工单。

想系统学会用 AI?报名体系课或加入会员,照着学、照着用。