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

Spring Boot 3中Oauth2ResourceServer自定义认证异常处理问题

解决Spring Boot 3 OAuth2资源服务器自定义AuthenticationManagerResolver异常传递问题

核心原因

自定义AuthenticationManagerResolver抛出的异常发生在Filter认证阶段,早于Spring MVC的DispatcherServlet执行,因此无法被@RestControllerAdvice直接捕获。默认的AuthenticationEntryPoint会覆盖原始异常,返回通用的InsufficientAuthenticationException,且无法自动获取MVC的HandlerExceptionResolver。

解决方案

通过自定义AuthenticationEntryPoint将原始异常委托给MVC的异常处理器,让@RestControllerAdvice能捕获并处理原始异常信息。

1. 自定义AuthenticationEntryPoint

注入MVC的HandlerExceptionResolver,将原始异常传递给MVC异常处理链:

@Component
public class CustomAuthEntryPoint implements AuthenticationEntryPoint {

    private final HandlerExceptionResolver exceptionResolver;

    // 主动注入HandlerExceptionResolver,解决默认null问题
    @Autowired
    public CustomAuthEntryPoint(HandlerExceptionResolver exceptionResolver) {
        this.exceptionResolver = exceptionResolver;
    }

    @Override
    public void commence(HttpServletRequest request, HttpServletResponse response, AuthenticationException authException) throws IOException, ServletException {
        // 将原始异常存入请求属性,便于后续处理器获取
        request.setAttribute("javax.servlet.error.exception", authException);
        // 委托给MVC异常处理器处理
        exceptionResolver.resolveException(request, response, null, authException);
    }
}

2. 配置SecurityFilterChain

将自定义的AuthenticationEntryPoint绑定到OAuth2资源服务器配置:

@Configuration
@EnableWebSecurity
public class SecurityConfig {

    private final CustomAuthEntryPoint customAuthEntryPoint;
    private final AuthenticationManagerResolver<HttpServletRequest> customAuthManagerResolver;

    @Autowired
    public SecurityConfig(CustomAuthEntryPoint customAuthEntryPoint,
                          AuthenticationManagerResolver<HttpServletRequest> customAuthManagerResolver) {
        this.customAuthEntryPoint = customAuthEntryPoint;
        this.customAuthManagerResolver = customAuthManagerResolver;
    }

    @Bean
    public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {
        http
                .oauth2ResourceServer(oauth2 -> oauth2
                        .authenticationManagerResolver(customAuthManagerResolver)
                        .authenticationEntryPoint(customAuthEntryPoint)
                )
                .exceptionHandling(exceptions -> exceptions
                        .authenticationEntryPoint(customAuthEntryPoint)
                );
        return http.build();
    }
}

3. 在@RestControllerAdvice中处理原始异常

直接捕获自定义认证异常或AuthenticationException,返回带原始消息的响应:

@RestControllerAdvice
public class GlobalExceptionHandler {

    @ExceptionHandler({CustomAuthException.class, AuthenticationException.class})
    public ResponseEntity<ErrorResponse> handleAuthExceptions(AuthenticationException ex) {
        ErrorResponse error = new ErrorResponse(HttpStatus.UNAUTHORIZED.value(), ex.getMessage());
        return new ResponseEntity<>(error, HttpStatus.UNAUTHORIZED);
    }

    // 自定义错误响应体
    static class ErrorResponse {
        private int status;
        private String message;

        public ErrorResponse(int status, String message) {
            this.status = status;
            this.message = message;
        }

        // getter和setter省略
    }
}

4. 自定义认证异常(可选)

如果需要抛出业务相关的认证异常,继承AuthenticationException确保被Spring Security正确捕获:

public class CustomAuthException extends AuthenticationException {
    public CustomAuthException(String msg) {
        super(msg);
    }
}

在AuthenticationManagerResolver中抛出该异常:

@Component
public class CustomAuthManagerResolver implements AuthenticationManagerResolver<HttpServletRequest> {

    @Override
    public AuthenticationManager resolve(HttpServletRequest request) {
        String authType = request.getHeader("X-Auth-Type");
        if (!"VALID_TYPE".equals(authType)) {
            throw new CustomAuthException("不支持的认证类型:" + authType);
        }
        // 返回对应AuthenticationManager逻辑
        return authentication -> authentication;
    }
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.04 19:40:26