SpringSecurity整合JWT时遇见的异常以及处理方式

SpringSecurity整合JWT时遇见的异常以及处理方式

一、问题背景及解决方案

​ SpringBoot整合SpringSecurity时有时候JWT会报错,

比如:

io.jsonwebtoken.SignatureException: JWT signature does not match locally computed signature. 
JWT validity cannot be asserted and should not be trusted.

解决方法(捕获该异常):

public class JWTAuthenticationFilter extends GenericFilterBean {
    
    
    @Override
    public void doFilter(ServletRequest request, ServletResponse response, FilterChain filterChain) throws IOException, ServletException {
    
    
        // 可以取到用户信息的(有正确token)将用户信息放入上下文
        try {
    
    
            Authentication auth = TokenAuthenticationService.getAuthentication((HttpServletRequest) request, (HttpServletResponse) response);
            SecurityContextHolder.getContext().setAuthentication(auth);
        } catch (MalformedJwtException | SignatureException | ExpiredJwtException | UnsupportedJwtException e) {
    
    
            SecurityContextHolder.getContext().setAuthentication(null);
        } finally{
    
    
            filterChain.doFilter(request, response);
        }
    }
}

二、JWT的异常

1、MalformedJwtException

这种异常说的是 token 格式不对。有时候会报这样的错:

io.jsonwebtoken.MalformedJwtException: JWT strings must contain exactly 2 period characters. Found:

// io.jsonwebtoken.MalformedJwtException:JWT字符串必须正好包含2个句点字符。找到:

2、SignatureException

这种异常说的是 token 签名不对。比较好理解,比如:

public static void addAuthentication(HttpServletResponse res, String username, String role) {
    
    
  String JWT = Jwts.builder()
    .setSubject(username)
    .setExpiration(new Date(System.currentTimeMillis() + EXPIRATIONTIME))
    .claim("roleName", role)
    .signWith(SignatureAlgorithm.HS512, SECRET)
    .compact();
  res.addHeader(HEADER_STRING, TOKEN_PREFIX + " " + JWT);
}
// parse the token.
Claims body = Jwts.parser()
  .setSigningKey(SECRET)
  .parseClaimsJws(token.replace(TOKEN_PREFIX, ""))
  .getBody();
String username = body.getSubject();

如果生成 token 和解析 token 使用的 SECRET 签名不一致就会报这个错误。所以再看上面问题的报错,就很明显了,就是token的签名不对。

3、ExpiredJwtException

这种异常就是 token 过期了报的异常。

4、UnsupportedJwtException

这种异常就是不支持的 Jwt 报的异常。

加了以上4种异常捕获,然后在 上下文 中将当前用户设为 null 即可,那么就相当于一个游客访问项目了。

其实以上异常根据字面意思就很好理解:Malformed:格式不正确、Signature:签名、Expired:期满(过期)、Unsupported:不支持的。

三、jwt验证token报错:io.jsonwebtoken.UnsupportedJwtException: Signed Claims JWSs are not supported的解决

这个是网上查相关资料时看的,因为我一直用的都是正确的 parseClaimsJws ,但是也记录一下,有个印象.

报错信息:

io.jsonwebtoken.UnsupportedJwtException: Signed Claims JWSs are not supported.
    at io.jsonwebtoken.JwtHandlerAdapter.onClaimsJws(JwtHandlerAdapter.java:50)
    at io.jsonwebtoken.impl.DefaultJwtParser.parse(DefaultJwtParser.java:487)
    at io.jsonwebtoken.impl.DefaultJwtParser.parseClaimsJwt(DefaultJwtParser.java:514)
    at com.glzt.test.util.JwtUtils.getClaimsFromToken(JwtUtils.java:120)
    at com.glzt.test.util.JwtUtils.memoryUserInRedis(JwtUtils.java:185)
    at com.glzt.test.util.JwtUtils.generateToken(JwtUtils.java:162)
    at com.glzt.test.util.JwtUtils.generateToken(JwtUtils.java:148)
// 错误写法:parseClaimsJwt
Jwts.parser().setSigningKey(SECRET).parseClaimsJwt(token.replace(TOKEN_PREFIX, "")).getBody();

// 正确写法:parseClaimsJws
Jwts.parser().setSigningKey(SECRET).parseClaimsJws(token.replace(TOKEN_PREFIX, "")).getBody();

猜你喜欢

转载自blog.csdn.net/weixin_44374025/article/details/126238699
今日推荐