1. JWT 简介

JWT(JSON Web Token)是一种标准,定义了在两方之间安全传输数据的紧凑方式。JWT 的 payload 是一个 JSON 对象,包含一些声明(claims)。由于经过数字签名,这些声明可以被验证方轻松验证和信任。JWT 可以使用密钥或公钥/私钥对进行签名

本教程将学习如何使用 Auth0 JWT Java 库创建和解析 JWT

2. JWT 结构

JWT 由三部分组成:

  • Header(头部)
  • Payload(载荷)
  • Signature(签名)

每部分都是一个 Base64 编码的字符串,用点号(.)分隔。

2.1. JWT 头部

JWT 头部通常包含两部分:令牌类型("JWT")和签名算法。

Auth0 Java JWT 库提供了多种签名算法实现,如 HMAC、RSA 和 ECDSA。

示例 JWT 头部:

{
  "alg": "HS256",
  "typ": "JWT"
}

此头部对象经 Base64 编码后形成 JWT 的第一部分。

2.2. JWT 载荷

JWT 载荷包含一组声明(claims)。声明是关于实体(如用户)的陈述及附加数据。

声明分三类:

  • 注册声明:预定义的标准声明(非强制),名称通常为 3 字符以保持 JWT 紧凑。常见示例:
    • iss(签发者)
    • exp(过期时间)
    • sub(主题)
  • 公共声明:可自定义使用
  • 私有声明:用于创建自定义声明

示例 JWT 载荷:

{
  "sub": "Baeldung Details",
  "nbf": 1669463994,
  "iss": "Baeldung",
  "exp": 1669463998,
  "userId": "1234",
  "iat": 1669463993,
  "jti": "b44bd6c6-f128-4415-8458-6d8b4bc98e4a"
}

⚠️ 注意:载荷中的 userId 是私有声明,表示登录用户 ID。其他声明提供 JWT 的附加信息。

载荷经 Base64 编码后形成 JWT 的第二部分。

2.3. JWT 签名

JWT 签名通过以下方式生成:使用签名算法和密钥对编码后的头部和载荷进行签名。签名用于验证 JWT 数据的完整性。

❗ 重要提示:

  • 任何人都能解码并查看 JWT 内容(仅 Base64 编码,非加密)
  • 签名仅验证声明完整性
  • 若使用公钥/私钥对签名,签名可证明仅私钥持有者能创建该令牌

最终组合三部分得到完整 JWT:

eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJzdWIiOiJCYWVsZHVuZyBEZXRhaWxzIiwibmJmIjoxNjY5NDYzOTk0LCJpc3MiOiJCYWVsZHVuZyIsImV4cCI6MTY2OTQ2Mzk5OCwidXNlcklkIjoiMTIzNCIsImlhdCI6MTY2OTQ2Mzk5MywianRpIjoiYjQ0YmQ2YzYtZjEyOC00NDE1LTg0NTgtNmQ4YjRiYzk4ZTRhIn0.14jm1FVPXFDJCUBARDTQkUErMmUTqdt5uMTGW6hDuV0

3. 使用 Auth0 库

Auth0 提供了易用的 Java 库来创建和管理 JWT。

3.1. 依赖配置

pom.xml 中添加 Maven 依赖

<dependency>
    <groupId>com.auth0</groupId>
    <artifactId>java-jwt</artifactId>
    <version>4.2.1</version>
</dependency>

3.2. 配置算法和验证器

首先创建 Algorithm 实例(本教程使用 HMAC256 算法):

Algorithm algorithm = Algorithm.HMAC256("baeldung");

✅ 此密钥将用于签名和验证 JWT。

接着初始化 JWTVerifier

JWTVerifier verifier = JWT.require(algorithm)
  .withIssuer("Baeldung")
  .build();

通过 JWT.require(Algorithm) 初始化验证器,返回 Verification 实例后构建 JWTVerifier

3.3. 创建 JWT

使用 JWT.create() 方法创建 JWT,返回 JWTCreator.Builder 实例。通过 Builder 设置声明并签名:

String jwtToken = JWT.create()
  .withIssuer("Baeldung")
  .withSubject("Baeldung Details")
  .withClaim("userId", "1234")
  .withIssuedAt(new Date())
  .withExpiresAt(new Date(System.currentTimeMillis() + 5000L))
  .withJWTId(UUID.randomUUID().toString())
  .withNotBefore(new Date(System.currentTimeMillis() + 1000L))
  .sign(algorithm);

生成的 JWT 示例:

eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJzdWIiOiJCYWVsZHVuZyBEZXRhaWxzIiwibmJmIjoxNjY5NDYzOTk0LCJpc3MiOiJCYWVsZHVuZyIsImV4cCI6MTY2OTQ2Mzk5OCwidXNlcklkIjoiMTIzNCIsImlhdCI6MTY2OTQ2Mzk5MywianRpIjoiYjQ0YmQ2YzYtZjEyOC00NDE1LTg0NTgtNmQ4YjRiYzk4ZTRhIn0.14jm1FVPXFDJCUBARDTQkUErMmUTqdt5uMTGW6hDuV0

常用 Builder 方法说明: | 方法 | 用途 | |------|------| | withIssuer() | 设置签发者 | | withSubject() | 设置主题 | | withIssuedAt() | 设置签发时间 | | withExpiresAt() | 设置过期时间 | | withJWTId() | 设置唯一标识符 | | withNotBefore() | 设置生效时间 | | withClaim() | 设置自定义声明 |

3.4. 验证 JWT

使用 JWTVerifier.verify(String) 验证 JWT

  • 若 JWT 有效,返回 DecodedJWT 实例
  • 若无效,抛出 JWTVerificationException

验证示例:

try {
    DecodedJWT decodedJWT = verifier.verify(jwtToken);
} catch (JWTVerificationException e) {
    System.out.println(e.getMessage());
}

获取声明示例:

Claim claim = decodedJWT.getClaim("userId");
String userId = claim.asString(); // 返回 "1234"

DecodedJWT 提供多种 getter 方法获取声明值。

💡 额外工具:Auth0 提供在线 JWT 调试器帮助解码和验证 JWT。

4. 总结

本文介绍了 JWT 的结构及其在认证中的应用。通过 Auth0 Java JWT 库,我们实现了:

  1. 使用签名、算法和密钥创建 JWT
  2. 验证令牌完整性
  3. 解码并获取声明

完整代码示例请访问 GitHub


原始标题:Managing JWT With Auth0 java-jwt