JWT(JSON Web Token)详解

536 阅读5分钟

JSON Web Token(JWT)是一种基于JSON的开放标准(RFC 7519),用于在网络应用间安全传递信息,特别适用于身份验证和授权场景。它通过数字签名确保数据的完整性和真实性,同时避免了传统会话认证的局限性(如服务器端状态存储问题)。

一、JWT的基本结构

JWT由三部分组成,通过点(.)连接:

  1. Header(头部)​

    • 包含令牌类型("typ": "JWT")和签名算法(如HMAC SHA256、RSA等)

    • 示例:

      {
        "alg": "HS256",
        "typ": "JWT"
      }
      
    • 这部分会被Base64Url编码

  2. Payload(负载)​

    • 存放声明信息(claims),包括:

      • 标准注册声明​:如iss(发行人)、exp(过期时间)、sub(主题)、aud(受众)等
      • 公共声明​:可自定义但需避免命名冲突
      • 私有声明​:为双方协商使用的自定义数据
    • 示例:

      {
        "sub": "user123",
        "name": "John Doe",
        "admin": true,
        "exp": 1735689600
      }
      
    • 这部分也会被Base64Url编码,但不加密,因此应避免存储敏感信息

  3. Signature(签名)​

    • 对Base64编码后的头部和负载进行签名,使用密钥(对称加密)或私钥(非对称加密)

    • 签名公式示例(HS256算法):

      HMACSHA256(base64UrlEncode(header) + "." + base64UrlEncode(payload), secret)
      
    • 用于确保数据未被篡改

最终的JWT格式为:Header.Payload.Signature,例如:

eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiaWF0IjoxNTE2MjM5MDIyfQ.SflKxwRJSMeKKF2QT4fwpMeJf36POk6yJV_adQssw5c

二、JWT的工作原理

  1. 用户认证​:客户端提交用户名和密码至认证服务
  2. 生成JWT​:服务器验证凭据后,生成包含用户信息的JWT并签名
  3. 存储与传输​:客户端将JWT存储在本地(如Cookie、LocalStorage),并在后续请求的HTTP头(如Authorization: Bearer <token>)中携带
  4. 验证与授权​:服务器解析JWT,验证签名有效性、过期时间及权限,若合法则返回资源

三、JWT的核心优势

  1. 无状态认证​:无需服务器存储会话信息,适合分布式系统和高并发场景
  2. 跨域支持​:可在不同服务间传递,适用于单点登录(SSO)和微服务架构
  3. 安全性​:签名机制防止数据篡改,支持非对称加密增强安全性
  4. 扩展性​:JSON格式灵活,可自定义负载内容
  5. 轻量级​:紧凑的字符串格式,传输开销小,各种语言都有库支持

四、JWT的局限性

  1. 不可撤销性​:JWT有效期内无法强制失效,需依赖短有效期或黑名单机制
  2. 负载数据暴露​:Base64编码可被解码,需避免存储敏感信息
  3. 签名密钥管理​:密钥泄露会导致安全风险,需严格保护
  4. 体积问题​:携带信息过多会导致token长度增加,影响传输效率
  5. 无法主动推送​:服务端无法像Session那样主动通知客户端续约或失效

五、JWT的应用场景

  1. 单点登录(SSO)​​:用户一次登录后访问多个关联系统
  2. API认证​:微服务间通过JWT传递身份信息,减少频繁鉴权开销
  3. 移动端认证​:无Cookie依赖,适合App与后端通信
  4. 信息交换​:不同系统之间安全传递信息,如Istio服务网格中的身份传递
  5. 密码重置​:生成包含重置信息的临时令牌

六、安全建议

  1. 使用HTTPS​:防止JWT在传输中被截获
  2. 短有效期​:设置合理过期时间(如30分钟),减少令牌泄露后的风险窗口
  3. 密钥轮换​:定期更新签名密钥以增强安全性
  4. 避免敏感数据​:负载中仅存储必要信息,敏感数据应加密
  5. 签名算法​:选择强签名算法(如HS256或RS256),避免使用"None"算法
  6. 黑名单机制​:对于注销功能,可使用Redis存储失效token

七、代码实现示例

Java实现(使用jjwt库)

// 生成JWT
public static String generateJwt(SecretKey secretKey) {
    Map<String, Object> claims = new HashMap<>();
    claims.put("userId", "12345");
    claims.put("username", "john_doe");
    claims.put("admin", true);

    return Jwts.builder()
        .setClaims(claims)
        .setSubject("User Authentication")
        .setIssuer("MyApp")
        .setIssuedAt(new Date())
        .setExpiration(new Date(System.currentTimeMillis() + 3600000)) // 1小时后过期
        .signWith(secretKey)
        .compact();
}

// 验证JWT
public static JwtResult validateJwt(String jwt, SecretKey secretKey) {
    try {
        Jws<Claims> claimsJws = Jwts.parserBuilder()
            .setSigningKey(secretKey)
            .build()
            .parseClaimsJws(jwt);
        return new JwtResult(true, claimsJws.getBody());
    } catch (Exception e) {
        return new JwtResult(false, null);
    }
}

八、JWT与Session的比较

特性JWTSession
状态管理无状态有状态(服务器存储)
扩展性适合分布式系统需要会话共享机制
安全性依赖签名和密钥依赖Session ID安全性
存储位置客户端存储服务器存储
跨域支持原生支持需要额外配置
失效控制依赖过期时间或黑名单可立即失效
数据携带可携带自定义数据通常只存储会话标识
性能影响每次请求需解析需要查询会话存储

九、高级主题

  1. 刷新令牌机制​:使用短期的访问令牌和长期的刷新令牌组合,平衡安全性与用户体验
  2. JWE(JSON Web Encryption)​​:对敏感负载内容进行加密,增强隐私保护
  3. 多因素认证集成​:在JWT claims中包含认证强度级别信息
  4. 微服务间的安全通信​:使用JWT作为服务网格中的身份凭证
  5. 合规性考虑​:满足GDPR等数据保护法规对令牌中个人信息存储的要求

十、总结

JWT通过紧凑的结构和安全的签名机制,成为现代无状态认证的主流方案。它特别适合分布式系统、微服务架构和跨域应用场景。然而,其设计需结合业务场景和安全需求,合理权衡便利性与风险。正确实现JWT认证需要考虑密钥管理、令牌有效期、传输安全等多方面因素,并可能需结合黑名单等补充机制来满足特定业务需求。