原理
TODO
简单测试
maven 添加以下依赖:
<dependency>
<groupId>io.jsonwebtoken</groupId>
<artifactId>jjwt-api</artifactId>
<version>0.11.2</version>
</dependency>
<dependency>
<groupId>io.jsonwebtoken</groupId>
<artifactId>jjwt-impl</artifactId>
<version>0.11.2</version>
<scope>runtime</scope>
</dependency>
<dependency>
<groupId>io.jsonwebtoken</groupId>
<artifactId>jjwt-jackson</artifactId> <!-- or jjwt-gson if Gson is preferred -->
<version>0.11.2</version>
<scope>runtime</scope>
</dependency>
encode
java code:
public class TempTest {
private static final Logger log = LoggerFactory.getLogger(TempTest.class);
public static void main(String[] args) {
String keyStr = "Boli's blog website: https://bolitao.xyz";
Key jwtKey = Keys.hmacShaKeyFor(keyStr.getBytes(StandardCharsets.UTF_8));
// 自定义 header parameters
Map<String, Object> headerParams = new HashMap<>(5);
headerParams.put("kid1", "myKeyId1");
headerParams.put("kid2", "myKeyId2");
// 自定义 claims
Map<String, Object> claims = new HashMap<>(5);
claims.put("claimKey1", "claimValue1");
claims.put("claimKey2", "claimValue2");
String jws = Jwts.builder().setSubject("Hello").setIssuedAt(new Date())
.setExpiration(new Date(System.currentTimeMillis() + 1000))
.setId(String.valueOf(UUID.randomUUID())).addClaims(claims)
.signWith(jwtKey).setHeaderParams(headerParams).compact();
log.info(jws);
}
}
output:
20:12:52.647 [main] INFO xyz.bolitao.jjwt_test.jjwt.TempTest - eyJraWQxIjoibXlLZXlJZDEiLCJraWQyIjoibXlLZXlJZDIiLCJhbGciOiJIUzI1NiJ9.eyJzdWIiOiJIZWxsbyIsImlhdCI6MTU5Njg4ODgzMSwiZXhwIjoxNTk2ODg4NzcxLCJqdGkiOiI2NDFkZWNlMC1kM2MzLTQ5ZmYtYTZiNy0xNDU5NmNjZDVlMGUiLCJjbGFpbUtleTEiOiJjbGFpbVZhbHVlMSIsImNsYWltS2V5MiI6ImNsYWltVmFsdWUyIn0.p0IXgzrK9yOUu4_QuKJ_0qYX5VKCL5sWEF-zATDmhJA
decode
添加以下代码:
log.info(String.valueOf(Jwts.parserBuilder().setSigningKey(jwtKey).build().parseClaimsJws("eyIxMjMiOiJxd2UiLCJraWQxIjoibXlLZXlJZDIxIiwia2lkMiI6Im15S2V5SWQyIiwiYWxnIjoiSFMyNTYifQ.eyJzdWIiOiJIZWwyMTMyMTMxMjNkbG8iLCJpYXQiOjE1OTY4ODk1ODQsImV4cCI6MTU5Njg5MzE4NCwianRpIjoiOTU2ZGVmM2ItNDJxd2UxZS00N2IxLWFmOTAtODRkN2FjN2NkZWIwIiwiY2xhaW1LZXkxIjoiY2xhaW1WYWx1ZTEiLCJjbGFpbUtleTIiOiJjbGFpbVZhbHVlMiJ9.Ke6mEdcWpzQCdkd_uS4T82oFgR4fM2fMwbvxSa2W2Z4")));
输出:
20:54:00.632 [main] INFO xyz.bolitao.jjwt_test.jjwt.TempTest - header={123=qwe, kid1=myKeyId21, kid2=myKeyId2, alg=HS256},body={sub=Hel213213123dlo, iat=1596889584, exp=1596893184, jti=956def3b-42qwe1e-47b1-af90-84d7ac7cdeb0, claimKey1=claimValue1, claimKey2=claimValue2},signature=Ke6mEdcWpzQCdkd_uS4T82oFgR4fM2fMwbvxSa2W2Z4
常见错误(以下情况不该信任 token):
-
过期
这是一个有效期仅为 1s 的 token:
过去数秒后,使用以下代码解析:
log.info(String.valueOf(Jwts.parserBuilder().setSigningKey(jwtKey).build().parseClaimsJws("eyJraWQxIjoibXlLZXlJZDEiLCJraWQyIjoibXlLZXlJZDIiLCJhbGciOiJIUzI1NiJ9.eyJzdWIiOiJIZWxsbyIsImlhdCI6MTU5Njg5MDk5MSwiZXhwIjoxNTk2ODkwOTkyLCJqdGkiOiI2NjI2M2UxMy00ZWZmLTRlZDItODBmYS0wZjZiMzA4Njg5MTEiLCJjbGFpbUtleTEiOiJjbGFpbVZhbHVlMSIsImNsYWltS2V5MiI6ImNsYWltVmFsdWUyIn0.8YmXYlpR6OJ4cxtDRvRVRRSgiQzNMjof904K7_xy4FU")));
会抛出 jwt 时间相关异常:
-
token 被修改
单独/同时修改 header、payload 或者 signature 都会抛出 JWT 相关的异常。
JJWT 源码
TODO