JWT中的ExpiredJwtException

前言

原本是调用jwtUtil(jwt的工具类),传入一个token,判断是否过期,然而却抛io.jsonwebtoken.ExpiredJwtException异常了,而业务中还需要根据是否过期进行刷新token!

io.jsonwebtoken.ExpiredJwtException: JWT expired at 2021-11-11T14:48:14Z. Current time: 2021-11-11T14:48:50Z, a difference of 36843 milliseconds.  Allowed clock skew: 0 milliseconds.
at io.jsonwebtoken.impl.DefaultJwtParser.parse(DefaultJwtParser.java:385)
at io.jsonwebtoken.impl.DefaultJwtParser.parse(DefaultJwtParser.java:481)
at io.jsonwebtoken.impl.DefaultJwtParser.parseClaimsJws(DefaultJwtParser.java:541)
at com.smart.util.JwtUtil.parseJwt(JwtUtil.java:63)
at com.smart.util.JwtUtil.isTokenExpired(JwtUtil.java:93)

问题所在

根据报错堆栈信息找到了DefaultJwtParser类中,找到了问题的原因

boolean allowSkew = this.allowedClockSkewMillis > 0L;
if (claims != null) {
Date now = this.clock.now();
long nowTime = now.getTime();
Date exp = claims.getExpiration();
String nbfVal;
SimpleDateFormat sdf;
if (exp != null) {
long maxTime = nowTime - this.allowedClockSkewMillis;
Date max = allowSkew ? new Date(maxTime) : now;
if (max.after(exp)) {
sdf = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss'Z'");
String expVal = sdf.format(exp);
nbfVal = sdf.format(now);
long differenceMillis = maxTime - exp.getTime();
String msg = "JWT expired at " + expVal + ". Current time: " + nbfVal + ", a difference of " + differenceMillis + " milliseconds. Allowed clock skew: " + this.allowedClockSkewMillis + " milliseconds.";
throw new ExpiredJwtException((Header)header, claims, msg);
}
}

在解析token并发现这个token已经过期了,它作出的反应是直接抛异常,除了msg信息,还有claims和header信息;
回到我们的工具类中的解析jwt的方法:

image-20211111173917609

private Claims getClaimsFromToken(String token) {
Claims claims;
try {
claims = Jwts.parser().setSigningKey(secret).parseClaimsJws(token).getBody();
} catch (Exception e) {
claims = null;
}
return claims;
}

解决

解析token会因为token过期而报异常,需要在异常也获取claims信息

claims = e.getClaims();异常后也能获取token里面的信息

刷新令牌不能和登录验证使用同一个函数,否则登录验证前端传来的token永远都有数据声明。

/**
* @author: chankeitin
* @description: 从令牌中获取数据声明-刷新令牌
* @date: 2021/11/11
* @param token
* @return io.jsonwebtoken.Claims
*/
private Claims getClaimsFromTokenToRefreshToken(String token) {
Claims claims;
try {
claims = Jwts.parser().setSigningKey(secret).parseClaimsJws(token).getBody();
} catch (ExpiredJwtException e) {
//解析token会因为token过期而报异常,需要在异常也获取claims信息
claims = e.getClaims();
}
return claims;
}