Spring Boot 3中JWT签名异常自定义处理方案咨询
解决Spring Boot 3 + Security 6中JWT SignatureException无法返回统一响应的问题
核心问题分析
你遇到的问题是SignatureException作为RuntimeException,未被过滤器捕获,直接被Spring Security默认异常机制处理,导致无法返回自定义的ApiError响应。另外代码存在逻辑反转:当前if (jwtService.isTokenValid(jwt))分支处理过期,但正常isTokenValid返回true代表令牌有效,返回false才是过期,这会导致逻辑错误。
解决方案步骤
1. 在过滤器中主动捕获SignatureException
修改doFilterInternal方法,将调用isTokenValid的代码包裹在try-catch块中,直接捕获JWT相关异常并调用错误处理方法:
protected void doFilterInternal( @NonNull HttpServletRequest request, @NonNull HttpServletResponse response, @NonNull FilterChain filterChain ) throws ServletException, IOException { String jwt = parseJwt(request); if (jwt != null) { try { boolean tokenValid = jwtService.isTokenValid(jwt); // 修正逻辑:令牌无效(过期)时返回错误响应 if (!tokenValid) { System.out.println("Token is expired"); handleAuthorisationDenied(response, "Unauthorised access: Security token expired"); return; } // 令牌有效则继续执行过滤器链 filterChain.doFilter(request, response); } catch (io.jsonwebtoken.security.SignatureException e) { // 处理签名异常 handleAuthorisationDenied(response, "Unauthorised access: Invalid JWT signature"); return; } catch (io.jsonwebtoken.ExpiredJwtException e) { // 单独处理过期异常 handleAuthorisationDenied(response, "Unauthorised access: Security token expired"); return; } catch (Exception e) { // 兜底处理其他JWT相关异常 handleAuthorisationDenied(response, "Unauthorised access: Invalid authentication token"); return; } } else { // 无令牌时继续执行(可根据业务需求调整为直接返回未授权) filterChain.doFilter(request, response); } }
2. 调整JwtService的isTokenValid方法
确保isTokenValid只处理过期判断,不要捕获SignatureException,让异常向上抛到过滤器处理:
public boolean isTokenValid(String jwt) { Claims claims = Jwts.parser() .setSigningKey(yourSecretKey) // 替换为你的签名密钥 .parseClaimsJws(jwt) .getBody(); // 判断令牌是否过期 return !claims.getExpiration().before(new Date()); }
如果需要单独处理过期异常,可在service中捕获ExpiredJwtException并返回false,让过滤器的!tokenValid分支处理:
public boolean isTokenValid(String jwt) { try { Claims claims = Jwts.parser() .setSigningKey(yourSecretKey) .parseClaimsJws(jwt) .getBody(); return !claims.getExpiration().before(new Date()); } catch (ExpiredJwtException e) { // 令牌过期返回false return false; } // 不要捕获SignatureException、MalformedJwtException等,让它们抛到过滤器处理 }
3. 验证异常处理逻辑
测试时携带无效签名的JWT令牌,此时SignatureException会被过滤器捕获,调用handleAuthorisationDenied返回自定义JSON错误响应,与过期令牌的处理逻辑保持一致。
内容的提问来源于stack exchange,提问作者fooshy
相关产品推荐
相关产品推荐

