JWT 协议详解:JSON Web Token 的架构、安全与标准
JWT(JSON Web Token,RFC 7519)是现代身份认证与授权领域最广泛使用的令牌协议之一。它通过标准化的三段式结构,实现了安全、紧凑的声明传递。本文将从协议架构、密码学机制、安全陷阱三个维度,完整解析 JWT 的设计原理与工程实践。
一、JWT 协议概述
1.1 标准体系
JWT 由 IETF 于 2015 年发布为 RFC 7519,配套定义了四个子标准:
| RFC 编号 | 名称 | 作用 |
|---|---|---|
| RFC 7515 | JWS:JSON Web Signature | 数字签名协议,定义签名生成与验证 |
| RFC 7516 | JWE:JSON Web Encryption | 加密协议,定义内容加密与密钥封装 |
| RFC 7517 | JWKS:JSON Web Key Set | 公钥集合格式,用于分发自签名公钥 |
| RFC 7518 | JOSE 算法注册表 | 签名与加密算法的官方注册表 |
1.2 核心设计目标
JWT 协议设计解决的核心问题是:如何在无状态环境下,安全地传递身份声明。
与传统的 session-based 认证相比,JWT 的优势在于:
- 无状态:服务端无需存储会话,适合分布式系统和微服务架构
- 自包含:Token 本身携带所有必要信息,减少跨系统查询
- 跨域友好:基于 JWT 的跨域认证无需 CORS 预检请求的额外开销
二、JWT 协议架构
2.1 三段式结构
JWT 采用三段式 Base64URL 编码结构,用 . 分隔:
Header.Payload.SignatureHeader(头部):包含令牌类型和签名算法,典型内容:
{
"typ": "JWT",
"alg": "HS256"
}Payload(载荷):包含声明(Claims),分为三类:
- Registered claims:预定义的标准声明(
iss、sub、aud、exp、nbf、iat、jti) - Public claims:各方协商的自定义声明
- Private claims:双方约定的私有声明
{
"sub": "1234567890",
"name": "John Doe",
"iat": 1516239022,
"exp": 1516242622,
"role": "admin"
}Signature(签名):对 Header 和 Payload 进行签名,确保完整性:
HMACSHA256(
base64UrlEncode(header) + "." +
base64UrlEncode(payload),
secret
)2.2 JWS(JSON Web Signature)
JWS 是 JWT 最常用的形式,提供签名的完整性保证。根据 RFC 7515,JWS 支持多种签名方案:
| 算法族 | 算法标识 | 说明 |
|---|---|---|
| HMAC | HS256、HS384、HS512 | 对称密钥签名,简单高效 |
| RSASSA-PKCS1-v1_5 | RS256、RS384、RS512 | RSA 经典签名方案 |
| RSASSA-PSS | PS256、PS384、PS512 | RSA 概率签名方案,更安全 |
| ECDSA | ES256、ES384、ES512 | 椭圆曲线数字签名算法 |
| EdDSA | Ed25519、Ed448 | Edwards 曲线签名,高性能 |
2.3 JWE(JSON Web Encryption)
JWE 提供加密保护,使 Token 内容仅对预期接收者可见。JWE 采用两层加密结构:
- 内容加密:使用内容加密密钥(CEK)加密 Payload
- 密钥封装:使用接收者公钥加密 CEK
| 类别 | 算法 | 说明 |
|---|---|---|
| 密钥封装 | RSA-OAEP、ECDH-ES、dir | 密钥加密方式 |
| 内容加密 | A128CBC-HS256、A256GCM | 数据加密方式 |
ProtectedHeader.EncryptedKey.IV.Ciphertext.AuthenticationTag2.4 JWKS(JSON Web Key Set)
JWKS 是用于分发公钥的标准化格式,常见于 OIDC 发现文档中:
{
"keys": [
{
"kty": "RSA",
"kid": "key-id-1",
"use": "sig",
"n": "yRiRE...",
"e": "AQAB"
}
]
}kty:密钥类型(RSA、EC、OKP)kid:密钥 ID,用于选择正确的公钥use:用途(sig 签名、enc 加密)
三、JWT 安全分析
3.1 算法混淆攻击(Algorithm Confusion)
风险等级:高危
攻击者将 Header 中的 alg 从非对称算法(如 RS256)改为对称算法(如 HS256),然后使用服务端公钥作为 HMAC 密钥签名。
防御措施:
- 服务端严格验证
alg字段,只接受预期的算法 - 验证 Token 时检查
kid与已知公钥匹配 - 使用
jwk参数或本地密钥配置替代远程 JWKS 动态加载
3.2 空签名攻击(Null Signature Attack)
风险等级:高危
攻击者将 alg 设置为 none,跳过签名验证。某些库默认允许此行为。
防御措施:
- 配置库时禁用
none算法 - 代码层面验证
alg不为none - 定期安全扫描 JWT 相关代码
3.3 密钥注入攻击(Key Injection)
风险等级:高危
攻击者篡改公钥或注入恶意 JWKS,使服务端使用攻击者控制的密钥验证签名。
防御措施:
- 固定信任的 JWKS 端点,禁用动态加载
- 对公钥进行摘要缓存和轮换检测
- 使用证书透明度(CT)验证公钥来源
3.4 过期时间缺失
风险等级:中危
Payload 中缺少 exp 字段,导致 Token 永不过期。
防御措施:
- 强制要求
exp字段存在且合法 - 设置合理的过期时间(建议不超过 15 分钟)
- 使用
nbf(not before)限制生效时间
四、JWT 在国密场景的适配
4.1 国密算法支持现状
当前 JWT 标准(RFC 7518)未包含国密算法,但可通过扩展实现:
| 国密算法 | JWT 对应 | 标准状态 |
|---|---|---|
| SM2 签名 | 无官方注册 | 需自定义 alg |
| SM3 哈希 | 无官方注册 | 需自定义 alg |
| SM4 加密 | 无官方注册 | 需自定义 alg |
4.2 自定义算法注册
根据 RFC 7518 第 3 节,可以通过 IANA 注册表或私有的 alg 值实现国密扩展:
{
"typ": "JWT",
"alg": "SM2-SM3"
}但需要注意:
- 自定义算法需确保跨平台兼容性
- 客户端和服务端需预先协商算法参数
- 避免与未来标准冲突
4.3 国密 JWT 应用场景
国密 JWT 主要应用于:
- 金融行业的身份认证
- 政务系统的跨域共享
- 电力、能源等关键基础设施的访问控制
五、JWT 与相关协议的关系
5.1 OpenID Connect(OIDC)
OIDC 在 OAuth 2.0 基础上增加了身份层,JWT 是其核心载体:
- ID Token:携带用户身份信息,使用 JWS 签名
- Access Token:可选使用 JWT 格式,或任意字符串
- UserInfo:基于 JWT 声明的用户信息端点
iss:Issuer(发行方)sub:Subject(用户唯一标识)aud:Audience(预期接收方)exp:Expiration timeiat:Issued at time
5.2 OAuth 2.0 Token Binding
OAuth 2.0 Token Binding(RFC 8320)扩展了 JWT 的使用场景,允许绑定访问令牌与 TLS 连接,防止令牌盗用。
5.3 CWT(CBOR Web Token)
CWT(RFC 8392)是 JWT 的 CBOR 版本,专为资源受限设备设计:
- 使用 CBOR 编码替代 JSON,更紧凑
- 支持 DTLS 环境下的轻量级认证
- 适用于 IoT 和嵌入式场景
六、工程实践建议
6.1 Token 生命周期管理
建议采用双层令牌策略:
- Access Token:短期有效(5-15 分钟),减少泄露影响范围
- Refresh Token:长期有效(天级),用于获取新的 Access Token
6.2 签名验证最佳实践
import jwt
# 安全验证示例
def verify_jwt(token, public_key, expected_alg="RS256"):
return jwt.decode(
token,
public_key,
algorithms=[expected_alg],
options={
"require": ["exp", "iat"],
"verify_exp": True,
"verify_iat": True,
},
issuer="https://your-issuer.com" # 验证发行方
)6.3 常见的错误实践
| 错误做法 | 风险 | 正确做法 |
|---|---|---|
使用 alg: none | 可被伪造 | 强制验签 |
| 密钥过长或过短 | 强度不足或存储困难 | RSA ≥ 2048 位,EC ≥ P-256 |
| 不过期或过期时间过长 | 泄露后永久有效 | Access Token 短期,Refresh Token 可控 |
| 在 Token 中存储敏感信息 | 信息泄露 | 只存非敏感声明,敏感数据服务端存储 |
| 明文存储 Token | 可被窃取 | 使用 HttpOnly Cookie 或安全存储 |
七、总结
JWT 协议通过标准化的三段式结构,实现了安全、紧凑的身份声明传递。其核心优势在于无状态和自包含,适合现代分布式系统。然而,算法混淆、空签名等安全风险要求开发者严格遵循安全实践:
- 算法验证:限制允许的算法白名单,防止混淆攻击
- 时间验证:强制检查
exp和iat字段 - 密钥管理:定期轮换密钥,固定信任的 JWKS 端点
- 最小声明:只在 Token 中存放必要的非敏感信息
相关标准
- RFC 7519: JSON Web Token (JWT)
- RFC 7515: JSON Web Signature (JWS)
- RFC 7516: JSON Web Encryption (JWE)
- RFC 7517: JSON Web Key (JWK)
- RFC 7518: JSON Web Algorithms (JWA)
- RFC 8747: OAuth 2.0 Token Binding
相关实践
- 国密算法在 JWT 中的应用实战 — 本文的详细工程实现案例