JWT(JSON Web Token)认证机制详解
请详细解释**JWT(JSON Web Token)**的结构和认证流程。JWT由哪三部分组成(Header/Payload/Signature)?JWT的签名算法(HS256/RS256)有什么区别?JWT存在哪些安全问题(如JWT alg=none漏洞、密钥泄露、过期时间)?如何安全使用JWT?
回答
Yahuda
JWT结构
JWT由三部分组成,以.分隔:xxxxx.yyyyy.zzzzz
1. Header(头部)
{"alg": "HS256", "typ": "JWT"}
2. Payload(载荷)
{
"sub": "1234567890", // 主题(用户ID)
"name": "John Doe",
"iat": 1516239022, // 签发时间
"exp": 1516242622, // 过期时间
"iss": "auth-service" // 签发者
}
3. Signature(签名)
HMACSHA256(base64UrlEncode(header) + "." + base64UrlEncode(payload), secret_key)
认证流程
用户登录 → 服务端验证凭据 → 生成JWT → 返回给客户端
客户端请求 → Header: Authorization: Bearer <JWT> → 服务端验证签名 → 放行
HS256 vs RS256
| 算法 | 类型 | 密钥 | 签名/验证 | 适用场景 |
|---|---|---|---|---|
| HS256 | 对称 | 同一密钥 | 签名和验证用同一个密钥 | 单服务/内部信任环境 |
| RS256 | 非对称 | 私钥签名+公钥验证 | 私钥签名,公钥验证 | 微服务/第三方分发 |
推荐用RS256:私钥仅认证中心持有,其他服务用公钥验证,密钥泄露风险低。
安全问题及防范
- alg:none攻击:修改Header中alg为"none"使签名验证跳过
- 防范:始终验证签名,禁止接受none算法
- 密钥混淆:RS256公钥加密的JWT被改为HS256,用公钥作为密钥验证
- 防范:固定算法,不允许客户端指定
- 暴力破解密钥:HS256使用弱密钥
- 防范:使用足够长(256bit+)的随机密钥
- Token泄露:JWT包含敏感信息在Payload中(Base64非加密)
- 防范:不放敏感信息,使用HTTPS
- Token过期未及时更新:
- 防范:短期access_token(15min) + 长期refresh_token
// JJWT库示例
String jwt = Jwts.builder()
.subject(userId)
.issuedAt(new Date())
.expiration(new Date(System.currentTimeMillis() + 3600_000))
.signWith(SignatureAlgorithm.RS256, privateKey)
.compact();