最近接手了一個后台,前端使用后端生成的合法token調用接口的時候會提示token無法解析,甩出了
io.jsonwebtoken.SignatureException: JWT signature does not match locally computed signature. JWT validity cannot be asserted and should not be trusted.
由於使用的框架和依賴是企業付費購買的,這里就不方便細述debug過程,最后debug時候發現在生成token前指定了JwtApi的JwtSecret
JwtApi jwtApi = JwtTokenApiFactory.createJwtApi(sysclient.getCaTokenSecret(),
sysclient.getTokenExpireSeconds());
public static JwtApi createJwtApi(String jwtSecret, Integer expiredSeconds) {
if (ObjectUtil.hasEmpty(jwtSecret, expiredSeconds)) {
throw new JwtException(JwtExceptionEnum.JWT_PARAM_EMPTY);
}
JwtConfig jwtConfig = new JwtConfig();
jwtConfig.setJwtSecret(jwtSecret);
jwtConfig.setExpiredSeconds(expiredSeconds.longValue());
return new JwtTokenOperator(jwtConfig);
}
String jwtToken = jwtApi.generateToken(payloadMap);
這樣的話在創建token時使用的secret和過期時間分別為:
但是在當前端帶着token去訪問接口時,在攔截器會做一個校驗:
public void validateToken(String token) {
// 校驗jwt token的正確性
boolean tokenFlag = jwtApi.validateToken(token);
// 如果token錯誤正確
if (!tokenFlag) {
throw new AuthException(AuthExceptionEnum.TOKEN_PARSE_ERROR);
}
// 校驗token在session緩存中是否存在
LoginUser session = sessionManagerApi.getSession(token);
if (session == null) {
throw new AuthException(AUTH_EXPIRED_ERROR);
}
}
@Override
public boolean validateToken(String token) {
try {
getJwtPayloadClaims(token);
return true;
} catch (io.jsonwebtoken.JwtException jwtException) {
return false;
}
}
@Override
public Claims getJwtPayloadClaims(String token) {
return Jwts.parser()
.setSigningKey(jwtConfig.getJwtSecret())
.parseClaimsJws(token)
.getBody();
}
但是這個時候的jwtConfig讀取的是配置文件中的配置
解決方法就是在調用jwtApi.validateToken(token)前先初始化jwtConfig進行賦值,或者統一數據庫和配置文件的秘鑰。