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