JWT令牌如何防止伪造?

wen 网络安全 68

本文目录导读:

JWT令牌如何防止伪造?

  1. 核心防线:数字签名
  2. 两种主流签名算法
  3. 其他关键防伪和安全性措施
  4. 完整的防伪流程

JWT(JSON Web Token)防止伪造的核心机制主要依赖于签名验证防篡改设计,以下是具体的防护机制和最佳实践:

核心防线:数字签名

JWT 由三部分组成:Header.Payload.Signature,防止伪造的关键在于第三部分——签名

  • 工作原理: 服务器在签发 JWT 时,会将 HeaderPayload 拼接起来,然后使用一个服务器端独有的密钥(Secret),通过指定的加密算法(如 HS256)生成一个签名,附加在令牌末尾。

  • 防伪机制: 当客户端将 JWT 发送回服务器时,服务器会使用同样的密钥和算法,对 HeaderPayload 重新计算签名,然后与 JWT 携带的签名进行比对。

    • 如果匹配:证明令牌在传输过程中未被篡改,且是由知道密钥的服务器签发。
    • 如果不匹配:服务器立即拒绝该请求。

关键点:攻击者不知道服务器端的密钥,无法生成一个合法的签名,如果攻击者篡改了 Payload(比如将 userId 从 “123” 改成 “456”),服务器重新计算的签名会与原来的签名不一致,导致验证失败。

两种主流签名算法

算法类型 算法示例 密钥管理 适用场景 安全性关键
对称加密 HS256 (HMAC + SHA256) 共享密钥(Secret),签发和验证都使用同一个密钥。 单服务器或内部微服务(链路可信)。 密钥绝对不能泄露,一旦泄露,任何人都可以伪造任意用户的 JWT。
非对称加密 RS256 (RSA + SHA256)
ES256 (ECDSA + SHA256)
公钥/私钥对。私钥用于签发(只在认证服务器保存),公钥用于验证(可分发到任何资源服务器)。 多服务架构、分布式系统、第三方应用集成。 私钥的安全是关键,公钥可以公开,但私钥必须严格保护,即使公钥泄露,攻击者也无法伪造签名。

为什么推荐 RS256/ES256?

  • 资源服务器只需要公钥,不需要接触私钥,降低了密钥泄露的风险。
  • 即使一个资源服务器被攻破,攻击者拿到公钥也无法签发新的 JWT。

其他关键防伪和安全性措施

仅仅依赖签名还不够,还需要配合以下措施:

a. 签名算法白名单

  • 漏洞示例:攻击者将 JWT 的 alg 字段从 "RS256" 改为 "none"(无签名算法)。
  • 防护必须在服务器端代码中明确指定允许的签名算法列表,并拒绝任何 alg: none 的令牌,否则,攻击者可以绕过签名验证。

b. 短有效期(Expiration Time, exp

  • JWT 的 Payload 应包含 exp 字段。
  • 原理:即使 JWT 被截获,攻击者只能在很短的时间内使用它(15 分钟或 1 小时)。
  • 最佳实践:使用 Access Token(短期) + Refresh Token(长期) 的模式,用户频繁刷新短期令牌,降低长期令牌的暴露风险。

c. 禁用一个已泄露的 JWT(黑名单/Revocation)

  • JWT 本身是无状态的,一旦签发,在过期前无法被服务器直接注销,但可以通过建立黑名单来模拟撤销。
  • 如何做:当用户登出或怀疑令牌泄露时,服务器将该 JWT 的 jti (JWT ID) 存入一个短生命周期的黑名单(如 Redis),服务器每次验证 JWT 时,先检查它是否在黑名单中。
  • 注意:这会增加服务器端状态,破坏了 JWT 完全无状态的优势,但有时是必要的。

d. 防止重放攻击

  • 手段:在 Payload 中包含 jti (唯一标识符) 和 iat (签发时间),并记录已使用过的 jti,确保同一个 JWT 不能被多次使用。
  • 适用场景:对幂等性要求极高的操作(如付款)。

e. 敏感信息不要放在 Payload 中(但这不是防伪造)

  • JWT 的 Payload 是 Base64 编码,而非加密,任何拿到令牌的人都可以解码读取。
  • 虽然这不直接导致伪造,但泄露敏感信息(如密码、手机号)会放大安全风险。永远不要在 Payload 中存放密码、信用卡号等核心敏感信息。

完整的防伪流程

  1. 用户登录:服务器验证身份后,使用私钥(RS256)签发 JWT。
  2. 后端验证
    • Step 1:解码 Base64 的 Header,获取 alg 字段,检查是否在算法白名单中(拒绝 none)。
    • Step 2:检查 exp (过期时间) 和 nbf (生效时间,可选) 是否有效。
    • Step 3(可选):检查 jti 是否在黑名单中。
    • Step 4:使用公钥对 Header + Payload 重新计算签名,并与 JWT 携带的签名比对。
    • 全部通过:请求合法,执行后续逻辑。
    • 任一失败:返回 401 Unauthorized。

一句话总结:JWT 通过对 Header 和 Payload 进行数字签名来防止伪造,只要服务器端的密钥(私钥)安全、签名算法不被绕过(如禁用 alg: none),并结合有效期和黑名单机制,JWT 就是安全的。

抱歉,评论功能暂时关闭!