JJWT
2020-04-16 本文已影响0人
又语
本文介绍基于 jjwt 的 JWT 实现方法。
目录
- jjwt 简介
- 代码示例
jjwt 简介
JJWT 是完全基于 JWT、JWS、JWE、JWK 和 JWA RFC 规范的 Java 实现,采用 Apache License 2.0 开源协议。
JJWT 支持的算法:
- HS256: HMAC using SHA-256
- HS384: HMAC using SHA-384
- HS512: HMAC using SHA-512
- ES256: ECDSA using P-256 and SHA-256
- ES384: ECDSA using P-384 and SHA-384
- ES512: ECDSA using P-521 and SHA-512
- RS256: RSASSA-PKCS-v1_5 using SHA-256
- RS384: RSASSA-PKCS-v1_5 using SHA-384
- RS512: RSASSA-PKCS-v1_5 using SHA-512
- PS256: RSASSA-PSS using SHA-256 and MGF1 with SHA-256
- PS384: RSASSA-PSS using SHA-384 and MGF1 with SHA-384
- PS512: RSASSA-PSS using SHA-512 and MGF1 with SHA-512
PS256
、PS384
和 PS512
需要 JDK 11 或合适的 JCA 供应商(如:BouncyCastle)
JJWT 还添加了一些规范外的方便扩展,包括:
- JWT Body 压缩,不只是 JWEs
- Claims 断言(需要指定值)
- 使用合适的 JSON 解析器完成 Claim POJO 的序列化和反序列化
- 基于期望的 JWA 算法的安全密钥生成
目前为止尚不支持的特性:
- JWE (JWT 加密)
代码示例
- 添加依赖
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<parent>
<artifactId>java-tutorial</artifactId>
<groupId>tutorial.java</groupId>
<version>1.0-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<properties>
<jackson.version>2.10.3</jackson.version>
</properties>
<artifactId>jwt-tutorial</artifactId>
<dependencies>
<dependency>
<groupId>io.jsonwebtoken</groupId>
<artifactId>jjwt-api</artifactId>
<version>0.11.1</version>
</dependency>
<dependency>
<groupId>io.jsonwebtoken</groupId>
<artifactId>jjwt-impl</artifactId>
<version>0.11.1</version>
<scope>runtime</scope>
</dependency>
<dependency>
<groupId>io.jsonwebtoken</groupId>
<artifactId>jjwt-jackson</artifactId>
<version>0.11.1</version>
<scope>runtime</scope>
</dependency>
<!-- JDK 10 及之前版本需要添加 bcprov-jdk15on 依赖 -->
<dependency>
<groupId>org.bouncycastle</groupId>
<artifactId>bcprov-jdk15on</artifactId>
<version>1.60</version>
<scope>runtime</scope>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.12</version>
<scope>test</scope>
</dependency>
</dependencies>
</project>
- 编写代码
package tutorial.jwt;
import io.jsonwebtoken.Claims;
import io.jsonwebtoken.Jws;
import io.jsonwebtoken.Jwts;
import io.jsonwebtoken.SignatureAlgorithm;
import io.jsonwebtoken.security.Keys;
import org.junit.Assert;
import org.junit.Test;
import java.security.Key;
import java.time.LocalDateTime;
import java.time.ZoneId;
import java.time.ZonedDateTime;
import java.util.Date;
public class JjwtTest {
@Test
public void test() {
// 生成签名密钥,通常密钥应该从应用配置中读取
Key key = Keys.secretKeyFor(SignatureAlgorithm.HS256);
String issuer = "Issuer";
String subject = "Subject";
// JWS 是签名后的 JWT
String jws = Jwts.builder()
.setIssuer(issuer)
.setExpiration(date(2020, 6, 30, 23, 59, 59))
.setSubject(subject)
.setAudience("Audience X")
.setNotBefore(date(2020, 1, 1, 0, 0, 0))
.setIssuedAt(date(2020, 1, 1, 0, 0, 0))
.setId("jwt-id-1")
.signWith(key)
.compact();
System.out.println(jws);
// 校验 JWT
Jws<Claims> claims = Jwts.parserBuilder().setSigningKey(key).build()
.parseClaimsJws(jws);
Assert.assertEquals(issuer, claims.getBody().getIssuer());
Assert.assertEquals(subject, claims.getBody().getSubject());
// 其它校验略 ...
}
private Date date(int year, int month, int day, int hour, int minute, int second) {
LocalDateTime localDateTime = LocalDateTime.of(year, month, day, hour, minute, second);
ZonedDateTime zonedDateTime = localDateTime.atZone(ZoneId.systemDefault());
return Date.from(zonedDateTime.toInstant());
}
}
如果验签失败则会抛出 SignatureException
(继承自 JwtException
)。