401 是什么
401 Unauthorized 这个名字容易误导:它真正的含义是「未认证」,也就是请求没有带上有效凭证,或者凭证已经失效。RFC 9110 §15.5.2 要求这类响应必须携带认证挑战头,告诉客户端该用什么方案来证明身份。它和 403 的分工是:401 表示身份还没被确认,重新认证可能解决问题;403 表示身份已经确认但权限不足,重新登录也于事无补。把两者混用会让客户端做出错误的补救动作。
基本信息
| 名称 | 401 Unauthorized(RFC 9110 §15.5.2) |
|---|---|
| 真实含义 | 未认证或认证失败,而不是没有权限 |
| 关键头部 | 认证挑战头,声明服务端接受的认证方案 |
| 常见方案 | 基础认证、令牌认证、摘要认证、客户端证书 |
| 与 403 区别 | 401 需要重新提供凭证,403 提供凭证也没用 |
典型使用场景
- 接口要求登录:请求没带凭证时返回 401 并声明方案
- 凭证过期:令牌失效后要求客户端走刷新流程
- 凭证被撤销:注销、改密或风控命中后立即失效
- 凭证格式错误:请求头拼错或前缀写错导致无法解析
- 多租户隔离:未绑定租户的请求先要求认证再判定归属
基础认证与令牌认证的交互
基础认证与令牌认证的交互
curl -si https://api.example.com/private # 首次请求不带凭证
# 响应会给出 401 与认证挑战头
# 挑战头会声明接受哪种方案,并给出领域名
curl -si -u user:pass https://api.example.com/private # 基础认证:命令行会自动编码
curl -si -H 'Authorization: Bearer eyJhbGciOi' https://api.example.com/me # 令牌认证认证方案对比
| 方案 | 凭证形式 | 适用与注意 |
|---|---|---|
| 基础认证 | 用户名口令编码后放在请求头 | 实现最简单,必须走加密通道,不适合长期凭证 |
| 令牌认证 | 不透明令牌或结构化令牌 | 接口首选,注意过期与撤销机制 |
| 摘要认证 | 挑战与应答计算得出的摘要 | 避免明文口令,但实现复杂、使用面窄 |
| 客户端证书 | 双向握手中出示证书 | 适合服务之间调用,运维成本较高 |
令牌刷新流程的要点
- 过期与无效要区分:过期对应可刷新,无效或签名错误应直接要求重新登录
- 刷新令牌本身也要有有效期,并支持单次使用后作废,降低被盗用风险
- 并发请求同时触发刷新时要加锁或合并,避免多个刷新请求互相作废
- 客户端收到未认证响应后只重试一次,避免在凭证彻底失效时形成请求风暴
响应体里给出机器可读的错误标识(例如区分「缺少凭证」「已过期」「已撤销」)能让客户端自动决定是刷新令牌还是跳转登录页,比只给一个状态码有用得多。
未认证响应不携带认证挑战头属于不规范实现,浏览器弹窗、命令行工具与各类客户端库都会因此无法正确处理,务必确认该头存在。
排障要点
| 现象 | 优先检查 |
|---|---|
| 浏览器反复弹认证框 | 挑战头的领域名与凭证是否匹配 |
| 接口一直未认证 | 请求头的字段名与方案前缀是否拼写正确 |
| 刚登录就失效 | 服务端与客户端时间是否同步、令牌有效期是否过短 |
| 部分客户端失败 | 该客户端是否支持服务端声明的认证方案 |
凭证管理的四个原则
- 凭证只走请求头,不要塞进地址参数或页面里的隐藏字段,否则会随日志与来源头泄漏
- 客户端与服务端时间要保持同步,否则合法令牌会被判定为已经过期或尚未生效
- 凭证失效后的行为要统一:全站跳登录或统一走刷新,不要一个页面一种处理
- 服务端要能主动吊销凭证,只依赖过期时间会让被盗用的凭证一直有效到自然到期