3. JWT核心概念
3.1 JWT定义
JWT(JSON Web Token) 是一种基于 JSON 的开放标准(RFC 7519),用于在各方之间以紧凑且自包含的方式安全地传输信息。JWT 通常用于身份认证和信息交换场景,其核心特点是:
- 紧凑(Compact):JWT 体积小,可通过 URL、POST 参数或 HTTP Header 快速传输。
- 自包含(Self-contained):JWT 本身携带了用户身份、权限等声明信息,无需频繁查询数据库。
- 防篡改(Tamper-proof):JWT 通过签名机制保证内容在传输过程中未被篡改。
💡 关键理解: JWT 不是加密数据,而是对数据进行签名。签名确保数据来源可信且未被篡改,但 JWT 的 Payload 默认是 Base64URL 编码,并非加密。敏感信息不应直接放入 JWT 的 Payload。
3.2 JWT结构
一个完整的 JWT 由三个部分组成,以点号(.)分隔:
xxxxx.yyyyy.zzzzz
│ │ │
│ │ └── Signature(签名)
│ └──────── Payload(载荷)
└───────────── Header(头部)
3.2.1 Header(头部)
Header 通常包含两部分信息:令牌类型(typ)和签名算法(alg)。
{
"alg": "HS256",
"typ": "JWT"
}
| 字段 | 含义 | 常见值 |
|---|---|---|
alg |
签名算法 | HS256(HMAC-SHA256)、RS256(RSA-SHA256) |
typ |
令牌类型 | JWT |
kid |
密钥标识(可选) | 用于多密钥场景 |
3.2.2 Payload(载荷)
Payload 是 JWT 的主体,包含声明(Claims)。声明分为三类:
- 注册声明(Registered Claims):预定义的标准字段,如
iss(签发者)、sub(主题)、exp(过期时间)、iat(签发时间)。 - 公共声明(Public Claims):自定义字段,需在 IANA JSON Web Token Registry 注册或使用防冲突命名。
- 私有声明(Private Claims):双方约定的自定义字段,如
user_id、role。
{
"sub": "1234567890",
"name": "张三",
"role": "admin",
"iat": 1516239022,
"exp": 1516242622
}
| 声明 | 全称 | 说明 |
|---|---|---|
iss |
Issuer | 签发者 |
sub |
Subject | 主题(通常为用户 ID) |
aud |
Audience | 接收方 |
exp |
Expiration Time | 过期时间(UNIX 时间戳) |
nbf |
Not Before | 生效时间 |
iat |
Issued At | 签发时间 |
jti |
JWT ID | 唯一标识,防重放 |
3.2.3 Signature(签名)
Signature 是对 Header 和 Payload 的签名,用于验证消息在传输过程中未被篡改。生成过程如下:
HMACSHA256(
base64UrlEncode(header) + "." + base64UrlEncode(payload),
secret
)
签名使用 Header 中指定的算法(如 HS256)和密钥(secret)对前两部分进行加密。接收方使用相同的密钥和算法重新计算签名,比对是否一致。
⚠️ 安全警告: 签名密钥必须严格保密。如果密钥泄露,攻击者可以伪造任意 JWT。在生产环境中,建议使用环境变量或密钥管理服务存储密钥,切勿硬编码在代码中。
3.3 JWT工作原理
JWT 的工作流程分为签发、传输和验证三个阶段。下图展示了完整的交互过程:
3.4 JWT 验证流程详解
服务器在收到 JWT 后,按以下步骤进行验证:
- 解析令牌:以点号(.)分割 JWT,获取 Header、Payload 和 Signature。
- Base64URL 解码 Header:读取
alg字段,确定签名算法。 - 重新计算签名:使用服务器密钥和指定算法,对
base64UrlEncode(header) + "." + base64UrlEncode(payload)重新签名。 - 比对签名:将重新计算的签名与 JWT 中的 Signature 进行比对。一致则通过,否则拒绝。
- 验证声明:检查
exp(是否过期)、nbf(是否生效)、iss(签发者是否可信)等。
🔑 核心要点: JWT 的无状态特性使其非常适合分布式系统。服务器无需存储会话信息,只需验证签名即可确认用户身份。但这也意味着 JWT 一旦签发,在过期前无法主动撤销,因此
exp 的设置至关重要。
3.5 JWT 与 Session 对比
| 特性 | JWT | Session |
|---|---|---|
| 存储位置 | 客户端(令牌自包含) | 服务器(内存/数据库) |
| 扩展性 | 天然支持分布式,无需共享存储 | 需要集中式 Session 存储(如 Redis) |
| 撤销能力 | 无法主动撤销,需等待过期 | 可随时删除 Session |
| 性能 | 验证快(仅计算签名) | 需查询存储,高并发下可能成为瓶颈 |
| 安全性 | 签名防篡改,但 Payload 可读 | 数据存储在服务器,客户端仅持有 ID |
⚠️ 常见误区: JWT 的 Payload 是 Base64URL 编码,不是加密。任何拥有令牌的人都可以解码查看内容。切勿在 Payload 中存放密码、信用卡号等敏感信息。如需加密,应使用 JWE(JSON Web Encryption)。