之前讲解了jwt的相关知识,有不了解的,可以查看相关的文章JWT简介-CSDN博客,本节不再介绍,主要讲解有关java中如何通过jjwt库产生jwt以及解析jwt的相关操作。
添加maven依赖
<dependency>
<groupId>io.jsonwebtoken</groupId>
<artifactId>jjwt-api</artifactId>
<version>0.12.6</version>
</dependency>
<dependency>
<groupId>io.jsonwebtoken</groupId>
<artifactId>jjwt-impl</artifactId>
<version>0.12.6</version>
<scope>runtime</scope>
</dependency>
<dependency>
<groupId>io.jsonwebtoken</groupId>
<artifactId>jjwt-jackson</artifactId> <!-- or jjwt-gson if Gson is preferred -->
<version>0.12.6</version>
<scope>runtime</scope>
</dependency>
请注意,上述 JJWT 依赖关系声明只有一个编译时依赖关系,其余的都声明为运行时依赖关系。这是因为 JJWT 的设计使您只依赖于经过明确设计的 API,供您在应用程序中使用,而所有其他内部实现细节(可能会在没有警告的情况下发生变化)都被归类为仅在运行时依赖。如果您想确保长期稳定地使用和升级 JJWT,这一点极为重要。
这样做的目的是为了让您受益:jjwt-api .jar 经过精心设计,确保它包含您所需的内容,并尽可能保持向后兼容,这样您就可以在编译范围内安全地依赖它。运行时 jjwt-impl .jar 策略为 JJWT 开发人员提供了随时随地更改内部软件包和实现的灵活性。这有助于我们更快、更高效地实现功能、修复错误并向您发送新版本。
创建JWT
String jwtToken = Jwts.builder()
.claim("name", "Jane Doe")
.claim("email", "jane@example.com")
.subject("jane")
.id(UUID.randomUUID().toString())
.issuedAt(Date.from(now()))
.expiration(Date.from(now().plus(5L, ChronoUnit.MINUTES)))
.compact();
log.info("jwt is: {}", jwtToken);
产生的token如下:
eyJhbGciOiJub25lIn0.eyJuYW1lIjoiSmFuZSBEb2UiLCJlbWFpbCI6ImphbmVAZXhhbXBsZS5jb20iLCJzdWIiOiJqYW5lIiwianRpIjoiYjNkYzYzM2UtZjFhZi00YzhhLWEwNTAtMGQzZDRkNGFmYmE4IiwiaWF0IjoxNzE5NTI4NzA4LCJleHAiOjE3MTk1MjkwMDh9.
上述生成 JWT 的代码不言自明,但让我们一步步检查如何生成 JWT 标记:
- 添加声明人姓名和电子邮件,值分别为 Jane Doe 和 jane@example.com
- 在 JWT 标记中添加主题,值为 jane
- 使用随机生成的 UUID 为 JWT 令牌设置 ID
- 将发布时间设置为当前时间
- 将过期时间设置为当前时间加 5 分钟。因此,JWT 的有效期只有 5 分钟
- 如果需要添加自定义的属性值,可以通过claim方法进行添加
可使用地址:JSON Web Tokens - jwt.io 对产生的jwt进行解析,如下图所示:
上面生成的 JWT 没有签名(检查标头中的 alg 属性)。我们只是以 JSON 格式对声明进行了编码。如果使用 JWT 进行身份验证或授权,建议签署 JWT,以便对其进行验证。
验证和解析JWT
要验证或解析 JWT 标记,需要使用 Jwts.parser() 方法。
Jwts.parser()
.unsecured()
.build()
.parseUnsecuredClaims(jwtToken);
解析未签名的jwt时,需要使用unsecured()方法,对于签名的jwt,后续介绍。
在解析 JWT 令牌时,我们需要通过签名密钥来验证 JWT 签名。让我们看看如何使用不同的算法签署 JWT 令牌。
创建并验证使用 HMAC Secret 签名的 JWT 令牌
创建签名 JWT 标记的最简单方法是使用 HMAC 密钥。HMAC 代表基于散列的消息验证码,是一种加密散列函数。它用于同时验证令牌的数据完整性和真实性。
创建用 HMAC 签名的 JWT 令牌
要创建使用 HMAC 共享秘密签名的 JWT 标记,我们需要使用 .signWith() 方法指定签名。
// Key is hardcoded here for simplicity.
// Ideally this will get loaded from env configuration/secret vault
String secret = "asdfSFS34wfsdfsdfSDSD32dfsddDDerQSNCK34SOWEK5354fdgdf4";
SecretKey key = Keys.hmacShaKeyFor(Decoders.BASE64.decode(secret));
Instant now = Instant.now();
String jwtToken = Jwts.builder()
.claim("name", "Jane Doe")
.claim("email", "jane@example.com")
.subject("jane")
.id(UUID.randomUUID().toString())
.issuedAt(Date.from(now))
.expiration(Date.from(now.plus(5L, ChronoUnit.MINUTES)))
.signWith(key)
.compact();
生成的 JWT 令牌:
eyJhbGciOiJIUzI1NiJ9.eyJuYW1lIjoiSmFuZSBEb2UiLCJlbWFpbCI6ImphbmVAZXhhbXBsZS5jb20iLCJzdWIiOiJqYW5lIiwianRpIjoiMGMxZDgzMGEtZjU5NC00MTQwLWI1YWMtYjE0ZTk2MTMyNDBkIiwiaWF0IjoxNzE5NTI5NTg2LCJleHAiOjE3MTk1Mjk4ODZ9.53vnen3J2qFVpbIGDhzvuXOySJX_zesTZuVYe9zM8JM
在header中的alg表明,签名使用的时HS-256算法。
验证/解析用 HMAC 签名的 JWT 令牌
要验证/解析使用 HMAC 共享密钥生成的 JWT 令牌,也可以采用相同的步骤。在解析 JWT 令牌之前,我们需要使用 verifyWith() 方法设置密钥。
final Jws<Claims> claimsJws = Jwts.parser()
.verifyWith(key)
.build()
.parseSignedClaims(jwtToken);
log.info("info is: {}", claimsJws);
如果 JWT 令牌过期(过期声明值小于当前系统时间),parseClaimsJws() 方法将抛出 SignatureException。
如果报出该错误 ,则说明jwt过期,需要返回401或者重定向到登录页。
以上是对于jjwt操作jwt的简单使用,基本可以适用于大部分应用常见,希望对您有所帮助。