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 库,我们实现了:
- 使用签名、算法和密钥创建 JWT
- 验证令牌完整性
- 解码并获取声明
完整代码示例请访问 GitHub。