问题背景
在使用SpringBoot做项目整合开发时,业务有需求,所以引入JWT来解决。但是在使用过程中发现了非常难搞的坑点。
坑点一
我是使用最新版本的jjwt,但导入时如果使用一个依赖,也就是如下:
<!-- https://mvnrepository.com/artifact/io.jsonwebtoken/jjwt-api -->
<dependency>
<groupId>io.jsonwebtoken</groupId>
<artifactId>jjwt-api</artifactId>
<version>0.12.6</version>
</dependency>
那很不幸,JWT最新版本貌似直接弃用了parseClaimsJws(token)方法,控制台会给你一个无厘头的报错:
java: 找不到符号
符号: 方法 parseClaimsJws(java.lang.String)
位置: 接口 io.jsonwebtoken.JwtParserBuilder
于是我尝试了其他方法,发现是依赖冲突问题,高版本的SpringBoot在使用JWT时需要将上面的依赖替换为下面这三个:
<dependency>
<groupId>io.jsonwebtoken</groupId>
<artifactId>jjwt-api</artifactId>
<version>0.12.6</version>
</dependency>
<!-- https://mvnrepository.com/artifact/io.jsonwebtoken/jjwt-impl -->
<dependency>
<groupId>io.jsonwebtoken</groupId>
<artifactId>jjwt-impl</artifactId>
<version>0.12.6</version>
</dependency>
<!-- https://mvnrepository.com/artifact/io.jsonwebtoken/jjwt-jackson -->
<dependency>
<groupId>io.jsonwebtoken</groupId>
<artifactId>jjwt-jackson</artifactId>
<version>0.12.6</version>
</dependency>
这下本以为没什么问题了,结果控制台还是报错:
java: 找不到符号
符号: 方法 parseClaimsJws(java.lang.String)
位置: 接口 io.jsonwebtoken.JwtParserBuilder
再次排查,还是从版本入手,将版本降低到0.11.5,问题终于解决。
坑点二
更令人摸不着头脑的是,最新版本的MyBatisPlus居然也不能完美契合这个版本的JWT,在最开始就需要找到能够和上述jwt契合的版本,我本来项目使用的版本是最新版本,即3.5.9,但是会报如下错误:
java: 无法访问com.baomidou.mybatisplus.extension.repository.IRepository
找不到com.baomidou.mybatisplus.extension.repository.IRepository的类文件
于是只能降级尝试,之后发现只有使用如下版本,才能避免冲突:
<!-- https://mvnrepository.com/artifact/com.baomidou/mybatis-plus-spring-boot3-starter -->
<dependency>
<groupId>com.baomidou</groupId>
<artifactId>mybatis-plus-spring-boot3-starter</artifactId>
<version>3.5.7</version>
</dependency>
<dependency>
<!-- https://mvnrepository.com/artifact/com.baomidou/mybatis-plus-extension -->
<groupId>com.baomidou</groupId>
<artifactId>mybatis-plus-extension</artifactId>
<version>3.5.7</version>
</dependency>
坑点三:
在配置好JWT依赖之后,我对jwt的初始化参数配置如下:
jwt:
token:
tokenExpiration: 120 #有效时间,单位分钟
tokenSignKey: ThisIsASecret #当前程序签名秘钥 自定义
尝试运行测试代码,控制台又报错了:
io.jsonwebtoken.security.WeakKeyException: The signing key's size is 80 bits which is not secure enough for the HS512 algorithm. The JWT JWA Specification (RFC 7518, Section 3.2) states that keys used with HS512 MUST have a size >= 512 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.HS512)' method to create a key guaranteed to be secure enough for HS512. See https://tools.ietf.org/html/rfc7518#section-3.2 for more information.
at io.jsonwebtoken.SignatureAlgorithm.assertValid(SignatureAlgorithm.java:387)
at io.jsonwebtoken.SignatureAlgorithm.assertValidSigningKey(SignatureAlgorithm.java:315)
at io.jsonwebtoken.impl.DefaultJwtBuilder.signWith(DefaultJwtBuilder.java:112)
at io.jsonwebtoken.impl.DefaultJwtBuilder.signWith(DefaultJwtBuilder.java:125)
at io.jsonwebtoken.impl.DefaultJwtBuilder.signWith(DefaultJwtBuilder.java:133)
at com.jinlei.utils.JwtHelper.createToken(JwtHelper.java:50)
at com.jinlei.test.SpringBootTest.test(SpringBootTest.java:23)
at java.base/java.lang.reflect.Method.invoke(Method.java:580)
at java.base/java.util.ArrayList.forEach(ArrayList.java:1597)
at java.base/java.util.ArrayList.forEach(ArrayList.java:1597)
根据报错信息提示,得知其原因是Key的数组位数不足。
于是进行各种尝试,最后使用了最笨的办法解决了该问题,修改配置文件中JWT的设置,将tokenSignKey:参数进行修改:
jwt:
token:
tokenExpiration: 120 #有效时间,单位分钟
tokenSignKey: ThisIsASecretThisIsASecretThisIsASecretThisIsASecretThisIsASecretThisIsASecretThisIsAS
只要将其长度设置到满足sha512即可(没深入研究JWt中这个算法是将一个字符按照多少bits存储的,我的字符串一共86个字符,按照他的算法满足512位,85个字符是510位,那么每个字符应该是按照6位来处理的)。
总结
很多时候,一股脑地在逻辑代码里寻找错误并不一定是最优解决思路,有时候多查查文章才能豁然开朗。在使用第三方提供的功能时,一定要注意版本之间可能存在的依赖冲突。