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,能生成/验证签名。


二、鉴权流程:无状态交互

Server Client Server Client POST /login (username, password) 验证凭证 返回 JWT (access_token) GET /api/profile (Header: Authorization: Bearer <JWT>) 1. 解码 JWT 2. 验证签名 3. 检查 exp/iss/aud 返回受保护资源
关键步骤(服务端验证):
  1. 解析 Token:按 . 分割三段。
  2. 验证签名:用本地 secret_key 重新计算签名,比对是否一致。
  3. 校验 Claims
    • exp 是否过期
    • iss 是否可信
    • aud 是否匹配当前服务
  4. 提取用户身份:从 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)

六、工程最佳实践

  1. Always use HTTPS:防止 Token 被中间人截获。
  2. Never store secrets in payload:Payload 是公开的。
  3. Validate all claimsexp, iss, aud 必须校验。
  4. Use strong keys
    • HS256:secret_key ≥ 32 字节随机字符串
    • RS256:RSA 2048 位以上
  5. Implement refresh token rotation:每次刷新返回新 Refresh Token,旧的立即失效。

总结

  • JWT 不是银弹:它解决的是无状态认证问题,而非所有安全问题。
  • 核心价值:去中心化验证、跨域支持、减少 DB 查询。
  • 致命缺陷:无法主动失效、信息泄露风险。
  • 正确姿势短期 Access Token + 可撤销 Refresh Token + 严格 Claim 校验

💡 一句话本质
JWT 是“一次性密码本”,签名保证真实性,有效期控制风险窗口。

Logo

有“AI”的1024 = 2048,欢迎大家加入2048 AI社区

更多推荐