JWT鉴权的庖丁解牛
JWT 不是银弹:它解决的是无状态认证问题,而非所有安全问题。核心价值:去中心化验证、跨域支持、减少 DB 查询。致命缺陷:无法主动失效、信息泄露风险。正确姿势短期 Access Token + 可撤销 Refresh Token + 严格 Claim 校验。💡一句话本质JWT 是“一次性密码本”,签名保证真实性,有效期控制风险窗口。
·
JWT(JSON Web Token)鉴权是一种无状态、自包含的认证机制,其核心在于 “信任签名,而非存储”。
一、JWT 结构:三段式 Base64Url 编码
xxxxx.yyyyy.zzzzz
↑ ↑ ↑
Header.Payload.Signature
1. Header(头部)
- 内容:
{ "alg": "HS256", "typ": "JWT" } - 作用:声明签名算法(
alg)和令牌类型(typ)。 - 编码:Base64Url →
eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9
2. Payload(载荷)
- 内容:业务数据 + 标准声明(Claims)
{ "sub": "1234567890", // 主题(用户ID) "name": "John Doe", "admin": true, "iat": 1516239022, // 签发时间 "exp": 1516242622 // 过期时间(关键!) } - 标准 Claims:
iss(签发者)、sub(主题)、aud(受众)exp(过期时间)、nbf(生效时间)、iat(签发时间)
- 编码:Base64Url →
eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiaWF0IjoxNTE2MjM5MDIyfQ
⚠️ Payload 未加密! 任何人可解码查看内容(仅防篡改,不防窥探)。
3. Signature(签名)
- 生成方式:
HMACSHA256( base64UrlEncode(header) + "." + base64UrlEncode(payload), secret_key ) - 作用:验证令牌未被篡改,且由可信方签发。
- 编码:二进制签名 → Base64Url
✅ 关键:只有服务端持有
secret_key,能生成/验证签名。
二、鉴权流程:无状态交互
关键步骤(服务端验证):
- 解析 Token:按
.分割三段。 - 验证签名:用本地
secret_key重新计算签名,比对是否一致。 - 校验 Claims:
exp是否过期iss是否可信aud是否匹配当前服务
- 提取用户身份:从
sub或自定义字段获取用户 ID。
✅ 无状态:服务端无需存储 JWT,所有信息自包含。
三、签名算法:对称 vs 非对称
| 算法类型 | 示例 | 密钥管理 | 适用场景 |
|---|---|---|---|
| 对称加密 | HS256, HS512 | 单一 secret_key(服务端保管) |
单体应用、内部服务 |
| 非对称加密 | RS256, ES256 | 私钥(签发)+ 公钥(验证) | 多服务、OAuth 2.0 |
为什么推荐 RS256?
- 安全隔离:验证方只需公钥,即使泄露也无法伪造 Token。
- 避免密钥分发:微服务架构中,各服务用同一公钥验证,无需共享
secret_key。
⚠️ 绝对禁止:
- 使用
none算法(无签名)- 客户端可控制
alg字段(导致算法混淆攻击)
四、核心安全陷阱与对策
1. Token 泄露 = 账号被盗
- 原因:JWT 一旦签发,在
exp前始终有效。 - 对策:
- 短有效期:Access Token 设为 15~30 分钟。
- Refresh Token 机制:
- Access Token 过期后,用 Refresh Token(存储在 HttpOnly Cookie)换取新 Token。
- Refresh Token 可撤销(需服务端存储黑名单或状态)。
2. 无法主动失效
- 问题:用户登出后,旧 Token 仍有效(因无状态)。
- 对策:
- 短期 Token:降低风险窗口。
- Token 黑名单:登出时将 Token 加入 Redis(
jti+exp),验证时检查。 - 版本号机制:用户表存
token_version,Payload 中带版本,不匹配则拒绝。
3. 敏感信息泄露
- 问题:Payload 可被 Base64 解码。
- 对策:绝不存放密码、身份证号等敏感数据。
4. 重放攻击(Replay Attack)
- 问题:截获 Token 后重复使用。
- 对策:
- 加入
jti(JWT ID) + 服务端记录已用 ID(短期存储)。 - 绑定客户端指纹(IP、User-Agent),但影响体验。
- 加入
五、与 Session 对比
| 特性 | JWT | Session |
|---|---|---|
| 状态 | 无状态(服务端不存) | 有状态(服务端存 Session) |
| 扩展性 | 天然适合分布式 | 需共享 Session 存储(Redis) |
| 安全性 | 依赖签名 + 短期有效 | 依赖 Cookie 安全(HttpOnly, Secure) |
| 撤销 | 困难(需额外机制) | 简单(删除 Session) |
| 体积 | 较大(含 Payload) | 小(仅 Session ID) |
✅ 选型建议:
- API 服务、移动端 → JWT
- 传统 Web 应用 → Session(更易管理登出、CSRF)
六、工程最佳实践
- Always use HTTPS:防止 Token 被中间人截获。
- Never store secrets in payload:Payload 是公开的。
- Validate all claims:
exp,iss,aud必须校验。 - Use strong keys:
- HS256:
secret_key≥ 32 字节随机字符串 - RS256:RSA 2048 位以上
- HS256:
- Implement refresh token rotation:每次刷新返回新 Refresh Token,旧的立即失效。
总结
- JWT 不是银弹:它解决的是无状态认证问题,而非所有安全问题。
- 核心价值:去中心化验证、跨域支持、减少 DB 查询。
- 致命缺陷:无法主动失效、信息泄露风险。
- 正确姿势:短期 Access Token + 可撤销 Refresh Token + 严格 Claim 校验。
💡 一句话本质:
JWT 是“一次性密码本”,签名保证真实性,有效期控制风险窗口。
更多推荐

所有评论(0)