JWT 的安全性是面试中常问的话题,以下是 JWT 的主要安全风险和防护措施:
主要安全风险
1. 算法混淆攻击 (Algorithm Confusion Attack)
攻击者将签名算法从非对称(如 RS256)改为对称(如 HS256),并使用公钥作为密钥来伪造签名。
防护措施:
- 严格验证签名算法,不允许客户端指定算法
- 在服务器端固定使用安全的签名算法
- 拒绝使用
none算法
2. Token 泄露
JWT 存储在客户端,可能通过 XSS 攻击被窃取。
防护措施:
- 使用 HttpOnly Cookie 存储 JWT,防止 JavaScript 访问
- 设置 SameSite 属性为 Strict 或 Lax,防止 CSRF 攻击
- 使用 HTTPS 传输,防止中间人攻击
- 设置较短的过期时间,并实现 Token 刷新机制
3. Payload 信息泄露
JWT 的 Payload 只是 Base64 编码,不是加密,任何人都可以解码查看。
防护措施:
- 不要在 Payload 中存储敏感信息(如密码、身份证号)
- 只存储必要的用户标识信息
- 如需传输敏感数据,使用 JWE (JSON Web Encryption)
4. Token 无法主动撤销
JWT 一旦签发,在过期前无法主动撤销。
防护措施:
- 设置合理的过期时间(通常 15-30 分钟)
- 实现 Token 黑名单机制(使用 Redis 存储)
- 使用 Refresh Token 机制,短期 Access Token + 长期 Refresh Token
- 在关键操作时进行二次验证
5. 重放攻击
攻击者截获有效的 JWT 并重复使用。
防护措施:
- 使用 jti (JWT ID) 声明,每个 Token 唯一
- 实现已使用 Token 的黑名单
- 添加 nonce 或时间戳验证
安全最佳实践
1. 签名算法选择
- HS256: HMAC SHA256,对称加密,密钥管理复杂
- RS256: RSA SHA256,非对称加密,更安全,推荐使用
- ES256: ECDSA SHA256,性能更好,签名更短
- 避免使用:
none算法、弱算法(HS1、HS512)
2. 密钥管理
- 使用足够强度的密钥(至少 256 位)
- 定期轮换密钥
- 密钥存储在安全的地方(环境变量、密钥管理服务)
- 不要在代码中硬编码密钥
3. Token 配置
javascript{ "iss": "your-domain.com", // 签发者 "sub": "user-id", // 主题 "aud": "your-api", // 受众 "exp": 1516239022, // 过期时间 "nbf": 1516239022, // 生效时间 "iat": 1516239022, // 签发时间 "jti": "unique-token-id" // JWT ID }
4. 传输安全
- 始终使用 HTTPS
- 在 Authorization Header 中传递:
Bearer <token> - 不要在 URL 中传递 JWT
5. 存储安全
- 优先使用 HttpOnly Cookie
- 如使用 LocalStorage,确保防范 XSS
- 实现 Token 自动刷新机制
6. 监控和审计
- 记录 Token 的签发、验证、刷新操作
- 监控异常的 Token 使用模式
- 实现速率限制,防止暴力破解
安全检查清单
- 使用强签名算法(RS256 或 ES256)
- 设置合理的过期时间
- 使用 HTTPS 传输
- 不存储敏感信息在 Payload 中
- 实现 Token 刷新机制
- 添加 jti 声明防止重放
- 使用 HttpOnly Cookie 存储
- 实现 Token 黑名单
- 密钥安全存储和定期轮换
- 监控和日志记录
通过以上措施,可以大大提高 JWT 的安全性。