JWT 基础概念:结构、编码与对比

JSON Web Token(JWT)是目前分布式系统中最常用的认证授权契约载体。理解 JWT 的结构、编码原理及其与 Session/Token 的区别,是设计安全接口契约的第一步。本章将拆解 JWT 的三个组成部分,解释 Base64Url 编码的动机,并通过对比表格明确 JWT 的适用场景。

2.1 JWT 的结构:三段式契约

一个 JWT 由三个用点号(.)分隔的 Base64Url 编码字符串组成:Header.Payload.Signature。每一段都承载特定的契约信息。

组成部分 位置 内容 是否加密 是否可篡改
Header(头部) 第一段 令牌类型(typ)和签名算法(alg),如 {"alg":"HS256","typ":"JWT"} 仅 Base64Url 编码,明文 篡改后签名验证失败
Payload(载荷) 第二段 声明(Claims):注册声明、公共声明、私有声明,如用户 ID、过期时间 仅 Base64Url 编码,明文 篡改后签名验证失败
Signature(签名) 第三段 对 Header 和 Payload 使用指定算法和密钥生成的签名 不可逆 验证失败则拒绝
关键认知:JWT 的 Payload 是明文编码,不是加密。不要在 Payload 中存放密码、信用卡号等敏感信息。签名仅保证数据完整性,不提供机密性。

下面通过一张结构图展示 JWT 的三段式组成与验证流程:

JWT 三段式结构 Header {"alg":"HS256","typ":"JWT"} Payload {"sub":"123","exp":1700000000} Signature HMACSHA256( base64UrlEncode(header) + "." + base64UrlEncode(payload), secret ) . . 验证流程:接收 JWT → 拆分三段 → 用 Header 中的算法 + 密钥对前两段重新签名 → 对比 Signature 签名匹配 → 信任 Payload

2.2 Base64Url 编码原理

JWT 使用 Base64Url 编码而非标准 Base64,主要为了解决 URL 传输中的兼容性问题。标准 Base64 包含 +、/ 和 = 三个特殊字符,在 URL 中需要额外转义。Base64Url 做了以下替换:

  • + 替换为 -(减号)
  • / 替换为 _(下划线)
  • 去除末尾的 =(填充字符)
编码示例:
原始 JSON: {"sub":"1234567890","name":"John Doe","iat":1516239022}
标准 Base64: eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiaWF0IjoxNTE2MjM5MDIyfQ==
Base64Url:   eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiaWF0IjoxNTE2MjM5MDIyfQ

解码时,只需逆向替换:将 - 换回 +,_ 换回 /,并根据长度补足 = 即可还原为标准 Base64 字符串。

2.3 JWT 与 Session / Token 的区别

在接口契约设计中,选择 JWT 还是传统 Session 或普通 Token,直接影响系统的可扩展性、安全性和性能。下表从多个维度进行对比:

对比维度 Session(服务端会话) 普通 Token(不透明令牌) JWT(自包含令牌)
存储位置 服务端内存/Redis 服务端数据库/缓存 客户端(无服务端存储)
状态类型 有状态 有状态 无状态
扩展性 差(需共享 Session 存储) 中(需共享 Token 存储) 好(任何服务节点均可验证)
信息携带 仅 Session ID 仅 Token 字符串 可携带用户信息、权限等
撤销机制 简单(删除 Session) 简单(删除 Token) 复杂(需黑名单或短有效期)
跨域支持 差(Cookie 受限) 好(Header 传递) 好(Header 传递)
性能开销 服务端查询开销 服务端查询开销 仅计算开销(无 I/O)
契约设计警示:JWT 的无状态特性是一把双刃剑。虽然它提升了扩展性,但一旦签发,在过期前无法主动撤销。对于需要即时权限变更的场景(如用户被禁用),必须配合短有效期(如 15 分钟)和刷新令牌机制,或维护一个黑名单。

下面通过一张架构对比图,直观展示 Session 与 JWT 在分布式系统中的差异:

Session vs JWT 架构对比 Session 架构(有状态) 客户端 服务端 A 服务端 B 共享 Session 存储 JWT 架构(无状态) 客户端 服务端 A 服务端 B 无需共享存储,各自验证签名

2.4 选择建议

在实际接口契约设计中,选择哪种方案取决于系统规模和安全要求:

  • 单体应用或小型系统:Session 方案简单直接,撤销方便,无需额外签名计算。
  • 微服务或分布式系统:JWT 的无状态特性可避免共享存储瓶颈,每个服务独立验证令牌。
  • 第三方 API 开放平台:JWT 作为自包含令牌,可携带权限范围(Scope),减少数据库查询。
  • 高安全敏感场景:建议使用 JWT + 短有效期 + 刷新令牌 + 黑名单的组合方案。
契约设计最佳实践:JWT 的 Payload 中应只包含非敏感的用户标识和权限声明。对于需要即时撤销的场景,将 JWT 的有效期控制在 15 分钟以内,并配合一个长期有效的刷新令牌(Refresh Token)存储在服务端,实现安全性与扩展性的平衡。