JWT 学习和 jjwt 的使用

jwt 学习和 jjwt 使用

原理

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):

  1. 过期

    这是一个有效期仅为 1s 的 token:

    过去数秒后,使用以下代码解析:

    log.info(String.valueOf(Jwts.parserBuilder().setSigningKey(jwtKey).build().parseClaimsJws("eyJraWQxIjoibXlLZXlJZDEiLCJraWQyIjoibXlLZXlJZDIiLCJhbGciOiJIUzI1NiJ9.eyJzdWIiOiJIZWxsbyIsImlhdCI6MTU5Njg5MDk5MSwiZXhwIjoxNTk2ODkwOTkyLCJqdGkiOiI2NjI2M2UxMy00ZWZmLTRlZDItODBmYS0wZjZiMzA4Njg5MTEiLCJjbGFpbUtleTEiOiJjbGFpbVZhbHVlMSIsImNsYWltS2V5MiI6ImNsYWltVmFsdWUyIn0.8YmXYlpR6OJ4cxtDRvRVRRSgiQzNMjof904K7_xy4FU")));
    

    会抛出 jwt 时间相关异常:

  2. token 被修改

    单独/同时修改 header、payload 或者 signature 都会抛出 JWT 相关的异常。

JJWT 源码

TODO

加载评论