理由:采用JWT的极大好处就是,将大部分的数据运算、存储压力给转移至前端而非服务端。
首先,导包:
import io.jsonwebtoken.Jwts;
import io.jsonwebtoken.SignatureAlgorithm;
import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.Test;
import javax.crypto.spec.SecretKeySpec;
import java.nio.charset.StandardCharsets;
import java.sql.Date;
import java.time.Duration;
import java.time.LocalDate;
import java.util.UUID;
然后上字符串生成、解析的使用案例:
@Test
void test01() {
final var signature = "test".repeat(8);
final var username = "James Gosling";
final var role = "Professor";
final var subject = "JWT-Demo";
final var uuid = UUID.randomUUID().toString();
final var JWT_TOKEN = Jwts.builder()
.setHeaderParam("typ", "JWT")
.setHeaderParam("alg", "HmacSHA256")
.claim("username", username)
.claim("role", role)
.setSubject(subject)
.setExpiration(Date.valueOf(LocalDate.now().plusDays(1)))
.setId(uuid)
.signWith(new SecretKeySpec(signature.getBytes(), "HmacSHA256"), SignatureAlgorithm.HS256)
.compact();
Assertions.assertNotNull(JWT_TOKEN);
//到此,JSON Web Token 已经成功生成,可以将此字符串发送给前端了
System.out.println(JWT_TOKEN);
final var jwtParser = Jwts.parserBuilder().setSigningKey(new SecretKeySpec(signature.getBytes(), "HmacSHA256")).build();
//下面就是进行JSON Web Token字符串的解析,并验证其操作耗时
Assertions.assertTimeout(Duration.ofMillis(36), () -> {
final var claimsJws = jwtParser.parseClaimsJws(JWT_TOKEN);
final var body = claimsJws.getBody();
final String s1 = body.get("username", String.class),
s2 = body.get("role", String.class),
s3 = body.getId(),
s4 = body.getSubject();
Assertions.assertEquals(s1, username);
Assertions.assertEquals(s2, role);
Assertions.assertEquals(s3, uuid);
Assertions.assertEquals(s4, subject);
System.out.writeBytes((
s1 + System.lineSeparator()
+ s2 + System.lineSeparator()
+ s3 + System.lineSeparator()
+ s4 + System.lineSeparator()
+ body.getExpiration() + System.lineSeparator())
.getBytes(StandardCharsets.UTF_8));
});
}
请注意:
-
HS256加密算法在Java中的标准称呼是HmacSHA256。如果名称错误,则会报错,抛出异常io.jsonwebtoken.security.InvalidKeyException。 例如:
io.jsonwebtoken.security.InvalidKeyException: The signing key's algorithm 'HS256' does not equal a valid HmacSHA* algorithm name and cannot be used with HS256.
- signature字符串的长度不可过短!否则将会抛出异常io.jsonwebtoken.security.WeakKeyException。
例如,把signature字符串常量更改为"test",而不去.repeat()。
io.jsonwebtoken.security.WeakKeyException: The signing key's size is 32 bits which is not secure enough for the HS256 algorithm. The JWT JWA Specification (RFC 7518, Section 3.2) states that keys used with HS256 MUST have a size >= 256 bits (the key size must be greater than or equal to the hash output size). Consider using the io.jsonwebtoken.security.Keys class's 'secretKeyFor(SignatureAlgorithm.HS256)' method to create a key guaranteed to be secure enough for HS256. See https://tools.ietf.org/html/rfc7518#section-3.2 for more information.
- java.security.Key 有很多实现子类,不一定非要new SecretKeySpec(byte[], String)。
- LocalDate.now().plusDays(1)表示明天的日期。