JWT安全详解
字数 1952 2025-11-13 16:32:16
JWT安全详解
描述
JSON Web Token(JWT)是一种开放标准(RFC 7519),用于在各方之间安全地传输信息作为JSON对象。它通常用于身份验证和授权场景。JWT由三部分组成:头部(Header)、载荷(Payload)和签名(Signature),用点分隔。虽然JWT设计是安全的,但错误实现或配置会导致严重漏洞,如身份伪造、信息泄露和权限提升。
解题过程
-
JWT结构分解
- 头部(Header):通常由两部分组成,令牌类型(即"JWT")和签名算法(如HMAC SHA256或RSA)。示例:
{"alg":"HS256","typ":"JWT"}。该JSON经过Base64Url编码形成第一部分。 - 载荷(Payload):包含声明(claims),即关于实体(如用户)和附加数据的语句。声明分三类:
- 注册声明(Registered claims):预定义声明,如"iss"(签发者)、"exp"(过期时间)、"sub"(主题)。
- 公开声明(Public claims):可自定义,但应避免与已注册声明冲突。
- 私有声明(Private claims):在同意使用它们的各方之间共享的自定义声明。
示例:{"sub":"1234567890","name":"John Doe","admin":true}。同样经过Base64Url编码形成第二部分。
- 签名(Signature):用于验证消息在传递过程中未被篡改。生成方式为:将编码后的头部和载荷用点连接,然后使用头部指定的算法和密钥进行签名。例如,HMAC SHA256算法的签名:
HMACSHA256(base64UrlEncode(header) + "." + base64UrlEncode(payload), secret)。
- 头部(Header):通常由两部分组成,令牌类型(即"JWT")和签名算法(如HMAC SHA256或RSA)。示例:
-
JWT工作流程
- 用户登录:客户端向服务器发送凭据(如用户名和密码)。
- 验证凭据:服务器验证凭据正确后,生成JWT(包括头部、载荷和签名),并返回给客户端。
- 客户端存储:客户端(如浏览器)将JWT存储在本地(通常为localStorage或cookie)。
- 后续请求:客户端在请求头(如Authorization: Bearer
)中携带JWT。 - 服务器验证:服务器检查JWT签名是否有效(使用相同密钥和算法重新计算签名并对比),并验证载荷中的声明(如过期时间)。验证通过后,处理请求。
-
常见安全漏洞及防御
-
算法混淆攻击(Algorithm Confusion):
- 原理:JWT头部"alg"字段指定验证签名时使用的算法。如果服务器配置为信任"alg"字段,攻击者可能将算法改为"none"(无签名)或从非对称算法(如RSA)改为对称算法(如HS256)。当改为HS256时,服务器可能使用公钥(本应公开)作为密钥来验证签名,而攻击者可用公钥生成有效签名。
- 防御:服务器应忽略JWT头中的"alg"字段,始终使用预期算法验证签名。或使用密钥时,明确区分对称密钥和非对称密钥对。
-
弱密钥(Weak Secret):
- 原理:使用HS256等对称算法时,如果密钥太弱(如"secret"、"password"),攻击者可能暴力破解密钥,从而伪造任意JWT。
- 防御:使用强随机密钥(如256位),并定期轮换。避免硬编码密钥,使用安全密钥管理服务。
-
未验证签名:
- 原理:服务器未验证JWT签名直接信任令牌内容,导致攻击者可修改载荷(如提升权限)而无需知道密钥。
- 防御:严格验证签名,失败则立即拒绝请求。
-
敏感信息泄露:
- 原理:JWT载荷仅经Base64Url编码(非加密),可被任何人解码。若在载荷中存储密码、密钥等敏感数据,会导致信息泄露。
- 防御:避免在JWT中存放敏感信息。如需保密,使用JWE(JSON Web Encryption)进行加密。
-
过期时间(exp)过长或未设置:
- 原理:若JWT过期时间设置过长或缺失,攻击者窃取令牌后可长期滥用。
- 防御:设置较短过期时间(如15-30分钟),并使用刷新令牌(Refresh Token)机制续签。
-
令牌撤销问题:
- 原理:JWT一旦签发,在过期前始终有效。服务器无法强制撤销单个令牌,除非更改密钥(影响所有用户)。
- 防御:维护令牌黑名单(如使用Redis存储已撤销令牌ID),或采用短期JWT结合状态化会话管理。
-
-
安全最佳实践
- 使用强算法(如RS256而非HS256,避免算法混淆)。
- 验证所有声明(如"iss"、"aud"、"exp")。
- 使用HTTPS传输JWT,防止中间人窃取。
- 存储JWT时避免XSS可访问的位置(如优先使用HttpOnly Cookie而非localStorage)。