实现 JWT 签名与验证
概述
RFC 7519 定义的 JSON Web Token(JWT)是用于 Web 应用程序认证和授权的紧凑、URL 安全的令牌。本技能涵盖使用 HMAC-SHA256、RSA-PSS 和 EdDSA 算法实现安全的 JWT 签名,以及验证、令牌过期、声明验证,并防御常见 JWT 攻击(算法混淆、none 算法、密钥注入)。
目标
- 使用 HS256、RS256、ES256 和 EdDSA 实现 JWT 签名
- 验证 JWT 签名并校验标准声明
- 实现令牌过期、not-before 和受众验证
- 防御算法混淆和 none 算法攻击
- 使用 JWK Sets 实现 JWT 密钥轮换
- 构建完整的认证中间件
核心概念
JWT 算法
| 算法 | 类型 | 密钥 | 安全级别 |
|---|---|---|---|
| HS256 | 对称(HMAC) | 共享密钥 | 128 位 |
| RS256 | 非对称(RSA) | RSA 密钥对 | 112 位 |
| ES256 | 非对称(ECDSA) | P-256 密钥对 | 128 位 |
| EdDSA | 非对称(Ed25519) | Ed25519 密钥对 | 128 位 |
常见 JWT 攻击
- 算法混淆(Algorithm Confusion):将 RS256 切换为 HS256,使用公钥作为 HMAC 密钥
- None 算法:设置 alg=none 绕过签名验证
- 密钥注入(Key Injection):在 JWK 头部嵌入密钥
- 弱密钥(Weak Secrets):暴力破解短 HMAC 密钥
- 令牌重放(Token Replay):在没有过期的情况下重用有效令牌
安全注意事项
- 始终根据白名单验证算法头部
- 生产环境中永远不要接受 alg=none
- 分布式系统使用非对称算法(RS256、ES256)
- 设置短过期时间(访问令牌 15 分钟)
- 实现令牌刷新机制
- 安全存储密钥(不要放在源代码中)
验证标准
- JWT 签名为所有算法产生有效令牌
- 签名验证拒绝被篡改的令牌
- 过期令牌被拒绝
- 算法混淆攻击被阻止
- None 算法被拒绝
- JWK 密钥轮换正常工作
- 声明验证强制执行所有必需声明