You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Spring Boot全局异常处理器未触发认证失败异常问题排查

问题原因及解决方案

核心问题1:异常类命名冲突

你自定义的AuthenticationException和Spring Security自带的org.springframework.security.core.AuthenticationException重名了。当Bearer Token无效时,Spring Security抛出的是自身的AuthenticationException,但你的全局异常处理器只监听你自定义的同名类,自然无法匹配触发。

核心问题2:过滤器链执行顺序限制

Spring Security的认证逻辑运行在DispatcherServlet之前的过滤器链中,默认@ControllerAdvice仅能捕获控制器层(@Controller/@RestController)抛出的异常,无法直接处理过滤器阶段的异常。


具体修复步骤

1. 重命名自定义异常类(避免冲突)

@ResponseStatus(HttpStatus.UNAUTHORIZED)
public class CustomAuthenticationException extends RuntimeException {
    public CustomAuthenticationException(String message) {
        super(message);
    }
}

2. 调整全局异常处理器,兼容Spring Security异常

修改处理器,同时支持处理Spring Security自带的认证异常和自定义异常:

@RestControllerAdvice
public class CustomizedResponseEntityExceptionHandler extends ResponseEntityExceptionHandler {

    // 处理Spring Security原生认证异常
    @ExceptionHandler(org.springframework.security.core.AuthenticationException.class)
    public ResponseEntity<ErrorResponse> handleSpringAuthException(org.springframework.security.core.AuthenticationException ex) {
        ErrorDetails errorDetails = new ErrorDetails(
                HttpStatus.UNAUTHORIZED.toString(),
                HttpStatus.UNAUTHORIZED.value(),
                ex.getMessage(),
                ex.getMessage(),
                new Date(),
                null
        );
        return new ResponseEntity<>(new ErrorResponse(List.of(errorDetails)), HttpStatus.UNAUTHORIZED);
    }

    // 处理自定义认证异常(可选)
    @ExceptionHandler(CustomAuthenticationException.class)
    public ResponseEntity<ErrorResponse> handleCustomAuthException(CustomAuthenticationException ex) {
        ErrorDetails errorDetails = new ErrorDetails(
                HttpStatus.UNAUTHORIZED.toString(),
                HttpStatus.UNAUTHORIZED.value(),
                ex.getMessage(),
                ex.getMessage(),
                new Date(),
                null
        );
        return new ResponseEntity<>(new ErrorResponse(List.of(errorDetails)), HttpStatus.UNAUTHORIZED);
    }
}

3. 修改认证入口点,将异常转发至DispatcherServlet

通过转发到/error端点,让DispatcherServlet接管异常处理,从而触发全局异常处理器:

@Component
public class AuthEntryPoint implements AuthenticationEntryPoint {

    @Override
    public void commence(HttpServletRequest request, HttpServletResponse response, org.springframework.security.core.AuthenticationException authException) throws IOException, ServletException {
        // 将异常绑定到请求属性,供DispatcherServlet识别
        request.setAttribute(DispatcherServlet.EXCEPTION_ATTRIBUTE, authException);
        // 转发到默认错误端点,触发全局异常处理器
        request.getRequestDispatcher("/error").forward(request, response);
    }
}

4. 确保Spring Security配置中启用自定义入口点

@Configuration
@EnableWebSecurity
public class SecurityConfig {

    @Autowired
    private AuthEntryPoint authEntryPoint;

    @Bean
    public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {
        http
                .authorizeHttpRequests(auth -> auth.anyRequest().authenticated())
                .oauth2ResourceServer(oauth2 -> oauth2
                        .jwt(Customizer.withDefaults())
                        .authenticationEntryPoint(authEntryPoint) // 绑定自定义入口点
                );
        return http.build();
    }
}

额外说明

  • 若不需要自定义异常,可直接删除自己的AuthenticationException类,仅保留处理Spring Security原生异常的处理器方法。
  • Spring Boot 3.x中,@RestControllerAdvice比@ControllerAdvice更适合处理REST接口的异常,无需额外配置@ResponseBody。

内容的提问来源于stack exchange,提问作者Arun

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.14 12:55:55