GeXiangDong

精通Java、SQL、Spring的拼写,擅长Linux、Windows的开关机

0%

jjwt 与 java-jwt 生成的jwt格式token互相解析

有2个java的库可以生成jwt,maven依赖分别如下

1
2
3
4
5
6
7
8
9
10
11
<dependency>
<groupId>io.jsonwebtoken</groupId>
<artifactId>jjwt</artifactId>
<version>0.7.0</version>
</dependency>

<dependency>
<groupId>com.auth0</groupId>
<artifactId>java-jwt</artifactId>
<version>3.10.3</version>
</dependency>

有在一个项目中用jjwt使用HS512方式做签名的token,使用同一个字符串作为key,但是在java-jwt中无法验证,出现错误:

Exception in thread “main” com.auth0.jwt.exceptions.SignatureVerificationException: The Token’s Signature resulted invalid when verified using the Algorithm: HmacSHA512

出错的代码

1
2
3
4
5
6
Jwts.builder()
.setClaims(map)
.setExpiration(new Date(t))
.signWith(SignatureAlgorithm.HS512, "helloworld")
.compact();

1
2
3
4
Algorithm algorithm = Algorithm.HMAC512("helloworld");
JWTVerifier verifier =
JWT.require(algorithm).acceptExpiresAt(5).build(); // Reusable verifier instance
DecodedJWT jwt = verifier.verify(t2);

原因

仔细查看代码后发现jjwt的签名参数传递错误导致,signWith的第二个参数时字符串,但是是需要的做base64后的字符串,在jjwt的源码中对传递进来的字符串参数做了base64 decode

参照: https://github.com/jwtk/jjwt/blob/master/impl/src/main/java/io/jsonwebtoken/impl/DefaultJwtBuilder.java

1
2
3
4
5
6
7
@Override
public JwtBuilder signWith(SignatureAlgorithm alg, String base64EncodedSecretKey) throws InvalidKeyException {
Assert.hasText(base64EncodedSecretKey, "base64-encoded secret key cannot be null or empty.");
Assert.isTrue(alg.isHmac(), "Base64-encoded key bytes may only be specified for HMAC signatures. If using RSA or Elliptic Curve, use the signWith(SignatureAlgorithm, Key) method instead.");
byte[] bytes = Decoders.BASE64.decode(base64EncodedSecretKey);
return signWith(alg, bytes);
}

解决方案

知道原因了就很容易解决了,最简单的方式两边加密解密的都用成 byte[] 做key,不会有base64 啥事。

或者jjwt加密时先把明文密码字符串做base64.Encode

1
2
3
4
5
6
String t2 =
Jwts.builder()
.setClaims(buyerMap)
.setExpiration(new Date(t))
.signWith(SignatureAlgorithm.HS512, Base64.encode("helloworld".getBytes()))
.compact();