1.问题理解
在运行别人项目(spring security整合jwt)时,发现这个偶发性的报错,导致登录权限功能一直无法运行,这个报错顾名思义就是JWT签名与本地计算的签名不匹配。JWT有效性无法断言,不应被信任,也就是说我们的jwt在项目运行过程中或者是认证过程中,可能出现了两个token,无法被区分
io.jsonwebtoken.SignatureException: JWT signature does not match locally computed signature. JWT validity cannot be asserted and should not be trusted.
同时我们还可以在JSON Web 令牌 - jwt.io平台验证自己生成的jwt是否符合规范
2.问题解决
(1)第一个可能的就是是否在项目里使用了两个密钥,也就是可能在其他地方也自定义了密钥,导致认证时认证了错误或不需要的密钥,又或者设置的密钥不符合规范都有可能,字节不够等等,这里建议将密钥定义为使用 HS512 算法创建和解析的 JWT 令牌
private static final SecretKey APP_SECRET = Keys.secretKeyFor(SignatureAlgorithm.HS512);
(2)第二个可能就是可能使用的jwt依赖版本过低,导致和项目不匹配等等都有可能,下面是我项目使用的依赖(仅供参考哈)
jwt依赖版本
<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> <version>0.11.2</version> <scope>runtime</scope> </dependency>
spring boot版本
<parent> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-parent</artifactId> <version>2.4.2</version> </parent>
(3)还有可能就是需要给jwt在创建和解析令牌时的密钥,加上编码设置,明确指定编码可以避免由于默认编码设置导致的问题,兼容性比较好,但如果我们使用的是SecretKey类型的密钥那就不需要设置编码了,因为 Jwts.builder().signWith() 方法可以直接接受 SecretKey对象
生成令牌时
.signWith(SignatureAlgorithm.HS512, APP_SECRET.getBytes(StandardCharsets.UTF_8))
解析令牌时
.setSigningKey(APP_SECRET.getBytes(StandardCharsets.UTF_8))
(4)清楚浏览器缓存
问题来了,以上这些建议我都修改了还是不行,问了AI很多次还是没能解决,后来慢慢知道了,既然是说签名不匹配,但是又是确定生成了正确的jwt后,有没有可能是缓存的问题导致的更新不及时,于是我重启了idea,重新运行项目,最关键的一步就是清楚浏览器缓存(Edge浏览器右上角三个点那,找到历史记录,找到垃圾箱图标),而且为了以防万一,每次执行项目前都要清楚缓存,至此,大功告成了