Spring Boot JWT非法Token异常处理:返回指定JSON响应需求
解决方案:捕获JWT格式异常并返回指定JSON响应
问题根源
你遇到的MalformedJwtException是在JWT认证Filter层抛出的,而非Controller层,所以单纯用@ExceptionHandler或JwtAuthenticationEntryPoint无法处理:
@ExceptionHandler仅能捕获Controller及后续流程抛出的异常JwtAuthenticationEntryPoint只负责处理未认证场景(如无Token、Token过期但格式合法),不处理Token格式错误的情况
实现步骤
1. 在JWT认证Filter中捕获异常并返回响应
修改你的JWT Filter类,在校验Token时主动捕获MalformedJwtException,记录日志后手动写入指定JSON响应:
@Component public class JwtAuthenticationFilter extends OncePerRequestFilter { private final JwtTokenProvider jwtTokenProvider; private final Logger logger = LoggerFactory.getLogger(JwtAuthenticationFilter.class); public JwtAuthenticationFilter(JwtTokenProvider jwtTokenProvider) { this.jwtTokenProvider = jwtTokenProvider; } @Override protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) throws ServletException, IOException { String token = extractTokenFromRequest(request); try { if (token != null && jwtTokenProvider.validateToken(token)) { Authentication auth = jwtTokenProvider.getAuthentication(token); SecurityContextHolder.getContext().setAuthentication(auth); } filterChain.doFilter(request, response); } catch (MalformedJwtException ex) { // 记录完整异常日志到控制台 logger.error("Invalid JWT token format detected", ex); // 返回指定JSON响应 sendCustomErrorResponse(response, HttpStatus.BAD_REQUEST, "Unable to read JSON value"); } } private String extractTokenFromRequest(HttpServletRequest request) { String bearerToken = request.getHeader("Authorization"); if (StringUtils.hasText(bearerToken) && bearerToken.startsWith("Bearer ")) { return bearerToken.substring(7); } return null; } private void sendCustomErrorResponse(HttpServletResponse response, HttpStatus status, String message) throws IOException { response.setStatus(status.value()); response.setContentType(MediaType.APPLICATION_JSON_VALUE); new ObjectMapper().writeValue(response.getWriter(), Collections.singletonMap("data", message)); } }
2. 配置全局异常处理器兜底
为了覆盖Controller层可能出现的同类异常,添加全局异常处理器:
@ControllerAdvice public class GlobalExceptionHandler { private final Logger logger = LoggerFactory.getLogger(GlobalExceptionHandler.class); @ExceptionHandler(MalformedJwtException.class) public ResponseEntity<Map<String, String>> handleMalformedJwt(MalformedJwtException ex) { logger.error("Malformed JWT token encountered", ex); Map<String, String> response = Collections.singletonMap("data", "Unable to read JSON value"); return new ResponseEntity<>(response, HttpStatus.BAD_REQUEST); } }
3. 确保Security配置正确
确认你的Security配置中已注册该Filter,且异常处理逻辑不冲突:
@Configuration @EnableWebSecurity public class SecurityConfig { private final JwtAuthenticationFilter jwtAuthFilter; private final JwtAuthenticationEntryPoint authEntryPoint; public SecurityConfig(JwtAuthenticationFilter jwtAuthFilter, JwtAuthenticationEntryPoint authEntryPoint) { this.jwtAuthFilter = jwtAuthFilter; this.authEntryPoint = authEntryPoint; } @Bean public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception { http .csrf(csrf -> csrf.disable()) .authorizeHttpRequests(auth -> auth .requestMatchers("/Login").permitAll() .anyRequest().authenticated() ) .exceptionHandling(ex -> ex.authenticationEntryPoint(authEntryPoint)) .addFilterBefore(jwtAuthFilter, UsernamePasswordAuthenticationFilter.class); return http.build(); } }
验证效果
修改Token首字符调用/Hello接口时:
- 控制台会打印完整的
MalformedJwtException堆栈日志 - 前端会收到响应:
{"data":"Unable to read JSON value"}
内容的提问来源于stack exchange,提问作者Akash Kashid
相关产品推荐
相关产品推荐

