JWT身份验证相关安全问题
字数 1385 2025-08-12 11:34:07
JWT身份验证安全教学文档
一、JWT基础介绍
1. JWT定义
JWT(JSON Web Token)是一种基于JSON的开放标准(RFC 7519),用于在网络应用环境间安全传递声明。它被设计为紧凑且安全,特别适用于分布式站点的单点登录(SSO)场景。
2. JWT组成结构
JWT由三部分组成,以"."分隔:
头部(Header).载荷(Payload).签名(Signature)
2.1 头部(Header)
- 包含令牌类型和加密算法
- 示例:
{
"alg": "HS256",
"typ": "JWT"
}
- 常用算法:
- HS256:对称算法
- RS256/ES256:非对称算法
2.2 载荷(Payload)
- 包含有效数据(claims)
- 标准字段:
- iss (issuer):发行者
- exp (expiration time):过期时间
- sub (subject):主题
- aud (audience):用户
- nbf (Not Before):生效时间
- iat (Issued At):签发时间
- jti (JWT ID):唯一标识
2.3 签名(Signature)
- 用于验证消息完整性
- 生成方式:
HMACSHA256(base64UrlEncode(header) + "." + base64UrlEncode(payload), secret)
二、JWT工作流程
- 用户登录,后端验证后返回JWT token
- 用户携带token访问受保护资源
- 服务端验证token签名
- 验证成功则允许访问
三、JWT安全漏洞与攻击方法
1. Secret硬编码漏洞
- 问题:开发者使用默认/硬编码的secret密钥
- 攻击:获取密钥后伪造任意token
- 防御:使用强随机secret并妥善保管
2. 签名未校验漏洞
- 问题:后端未验证Signature字段
- 攻击:直接修改payload或删除签名
- 防御:严格校验签名有效性
3. alg=none签名绕过(CVE-2015-2951)
- 问题:未校验header中的alg字段
- 攻击:将alg设为"none"并删除签名
- 防御:明确指定允许的算法并验证
4. Secret爆破攻击
- 问题:使用弱secret密钥
- 攻击:使用工具爆破secret
- 工具:jwt_tool(https://github.com/ticarpi/jwt_tool)
- 防御:使用强随机secret
5. 算法混淆攻击(CVE-2016-10555)
- 问题:RS256算法系统接受HS256算法token
- 攻击:
- 将alg从RS256改为HS256
- 使用公钥作为HS256的secret伪造token
- 防御:严格校验算法类型
6. 伪造密钥攻击(CVE-2018-0114)
- 问题:使用JWS存储公钥
- 攻击:
- 生成自己的公私钥对
- 用私钥生成token
- 将自生成的公钥放入JWS
- 防御:使用可信的密钥管理机制
四、防御措施总结
- 使用强随机secret并妥善保管
- 严格校验签名有效性
- 明确指定允许的算法并验证
- 使用非对称算法时确保私钥安全
- 实现token过期和刷新机制
- 避免在payload中存储敏感信息
- 使用HTTPS传输token
- 定期轮换密钥
五、工具与资源
- JWT调试工具:https://jwt.io/
- JWT攻击工具:https://github.com/ticarpi/jwt_tool
- JWT规范:RFC 7519
六、示例代码
1. 生成JWT token(Python)
import jwt
payload = {
"identity": 1,
"scope": "lin",
"type": "access",
"exp": 1659797574
}
# 安全方式
token = jwt.encode(payload, "your-strong-secret", algorithm="HS256")
# 不安全方式(alg=none攻击)
insecure_token = jwt.encode(payload, None, algorithm="none")
2. 验证JWT token(Java)
// 使用auth0库验证
try {
Algorithm algorithm = Algorithm.HMAC256("your-strong-secret");
JWTVerifier verifier = JWT.require(algorithm)
.build();
DecodedJWT jwt = verifier.verify(token);
} catch (JWTVerificationException exception){
// 无效签名
}
通过理解这些安全问题和防御措施,开发者可以更安全地实现JWT身份验证机制。