Deep Research: [70] JWT(RFC 7519):令牌不是字符串,是可审计的契约¶
- Source: https://www.rfc-editor.org/rfc/rfc7519
- Note: ../notes/ref-070-jwt.md
- Snapshot: ../sources/md/www-rfc-editor-org-rfc-rfc7519-7bb6aaba0f31.md
- Category: User / Auth / Audit (user_auth)
- Chapters: 09-backend, 11-user
TL;DR¶
JWT 不仅仅是一串用于传递的字符,它是一份经过数字签名、防篡改的、自包含的身份与权限契约。它的核心价值在于通过标准化的声明(Claims)将认证逻辑从中心化数据库查询下放到端侧/服务侧校验,是现代分布式架构和 AI Agent 交互中无状态信任的基石。
核心观点¶
- 自包含的信任状(Self-contained):JWT 内部携带了关于主体的所有必要信息(用户 ID、角色、过期时间),服务接收方无需回查中心数据库即可完成鉴权,这对于微服务和高并发 AI 推理场景至关重要。
- 声明即逻辑(Claims define Logic):RFC 7519 定义了
iss(签发者)、sub(主体)、aud(受众)、exp(过期时间)等标准字段。验证 JWT 实际上就是在验证这些字段是否符合当下的业务上下文(契约履行)。 - 签名非加密(Signed != Encrypted):标准 JWT(JWS)仅保证内容未被篡改,载荷(Payload)只是 Base64 编码,默认是公开透明的。切勿在未加密的 JWT 中放入密码、手机号等敏感隐私。
- 受众限制(Audience Restriction):
aud字段极其关键但常被忽略。它指定了令牌的合法使用者,防止发给服务 A的令牌被恶意重放到服务 B使用。 - 不可撤销性悖论:由于 JWT 的无状态特性,一旦签发,在
exp到期前理论上一直有效。必须配合黑名单机制或短期 Token + 长期 Refresh Token策略来解决注销和封禁问题。 - 算法协商的陷阱:JWT 头部包含加密算法字段(如 HS256, RS256),但验证方绝不能盲目信任头部指定的算法(特别是要防御
alg: none攻击),必须强制指定允许的算法列表。
可落地做法¶
1. 产品定义(第 3、11 章)¶
- 定义有效期策略:区分访问令牌(Access Token,建议 5-15 分钟)和刷新令牌(Refresh Token,建议 7-30 天)。前者用于高频 API 调用,后者用于静默续期。
- 最小化字段:只放入系统通用的 ID(如
user_id、tenant_id)和权限范围(scopes),避免放入变动频繁的业务数据(如vip_level),以免数据变更导致令牌数据陈旧。
2. 工程实现(第 7、9 章)¶
- 强制校验三要素:所有网关或验证中间件必须校验
exp(是否过期)、iss(是否由可信服务签发)、alg(是否为预期算法)。 - 密钥管理:对称加密(HS256)仅适用于单体应用;微服务或对外开放 API 应使用非对称加密(RS256/ES256),私钥签发,公钥验证。
- 解决注销延迟:在 Redis 中维护一个基于
jti(JWT ID)或user_id的失效时间戳或黑名单,在网关层做轻量级阻断。
3. 评测与安全(第 18 章)¶
- 安全扫描:测试将 header 中的
alg修改为none,移除签名部分,检查接口是否报错。 - 过期测试:构造已过期的 Token,验证接口返回 401 而非 500 或 200。
检查清单:JWT 安全实现¶
- [ ] 算法白名单:验证器代码中是否硬编码了允许的算法(如
RS256),并拒绝none? - [ ] 强校验过期:是否开启了严格的
exp校验,并处理了时钟偏差(Clock Skew,通常允许 30-60 秒误差)? - [ ] 敏感信息隔离:Payload 中是否不包含任何 PII(个人敏感信息)或机密数据?
- [ ] 受众检查:如果令牌用于特定服务,是否校验了
aud字段匹配当前服务标识? - [ ] 密钥强度:HMAC 密钥长度是否至少 256 位?RSA 密钥长度是否至少 2048 位?
- [ ] 传输安全:JWT 是否强制仅通过 HTTPS 传输?(防止中间人窃取令牌)
- [ ] 日志脱敏:应用日志中是否对 JWT 进行了脱敏处理(仅记录
jti或掩码处理)?
常见坑与对策¶
- 坑:把 JWT 当 Session 用,一旦用户修改密码或被封禁,手里的旧 JWT 依然有效。
- 对策:引入版本号或最后修改时间戳。在签发 JWT 时写入
iat(签发时间),验证时检查该用户在 DB/缓存中的last_logout_time,若iat < last_logout_time则拒绝。
- 对策:引入版本号或最后修改时间戳。在签发 JWT 时写入
- 坑:令牌体积过大,导致 HTTP Header 超限。
- 对策:控制 Payload 大小,不要把全量的用户 Profile 或权限树塞进去。仅放角色 ID 或权限组 ID。
- 坑:多个环境(Dev/Prod)共用密钥。
- 对策:严格隔离不同环境的密钥(Secret/Keypair),防止开发环境泄漏导致生产环境被伪造。
可用于丰富《AI 辅助软件产品》的写作点¶
- 第 5 章(MVP 后端骨架):在讲解 API 鉴权时,通过 RFC 7519 引入标准化的 Token 结构。对比传统 Session与JWT在 AI 流式响应(WebSocket/SSE)中的优势(减少握手时的数据库压力)。
- 第 10 章(Agent 架构与 RAG):Agent 间的信任传递。当 Agent A 调用 Agent B 时,如何通过 JWT 的
aud和scope声明,实现细粒度的工具调用权限控制(例如:只允许搜索工具,不允许删除文件工具)。 - 第 11 章(用户模块与审计):利用
jti(JWT ID)构建全链路可观测性。将jti注入到所有微服务的 Trace Context 中,实现从用户点击到底层 LLM 调用的完整审计链路。 - 第 17 章(部署与运维):介绍 Sidecar 模式(如 Envoy/Istio)如何利用 JWT 的标准结构(JWKS 协议)在网关层统一处理认证,让业务代码纯粹化。