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

在OAuth2中处理AuthenticationException:ResourceServerConfigurerAdapter场景方案咨询

解决ResourceServerConfigurerAdapter下AuthenticationException无法被@ControllerAdvice捕获的问题

我之前在Spring Security OAuth2资源服务器项目里也踩过这个坑——用@ControllerAdvice和@ExceptionHandler根本抓不到认证阶段抛出的AuthenticationException,后来才搞明白:这些异常是在Spring Security的过滤器链里抛出的,还没到Controller层呢,所以Controller层面的异常处理器根本碰不到它们。

你之前试的AuthenticationFailureHandler确实不适用,因为它主要是处理表单登录、用户名密码认证失败这类场景,而资源服务器的认证逻辑是基于Token校验的,走的是OAuth2专属的过滤器流程,所以那套方案行不通。

下面给你两个亲测有效的解决方案:

方案一:自定义AuthenticationEntryPoint处理未认证异常

AuthenticationEntryPoint是Spring Security专门用来处理未认证请求的接口,包括各种AuthenticationException(比如Token无效、Token过期、没有携带Token等)。你可以实现这个接口,自定义返回的响应格式,然后配置到ResourceServer的安全配置里。

1. 实现自定义AuthenticationEntryPoint

@Component
public class CustomAuthEntryPoint implements AuthenticationEntryPoint {

    @Override
    public void commence(HttpServletRequest request, 
                         HttpServletResponse response, 
                         AuthenticationException authException) throws IOException {
        // 设置响应格式和状态码
        response.setContentType("application/json;charset=UTF-8");
        response.setStatus(HttpServletResponse.SC_UNAUTHORIZED);
        
        // 自定义返回内容
        Map<String, Object> result = new HashMap<>();
        result.put("code", 401);
        result.put("message", "认证失败:" + authException.getMessage());
        result.put("timestamp", LocalDateTime.now().toString());
        
        // 写入响应
        ObjectMapper objectMapper = new ObjectMapper();
        objectMapper.writeValue(response.getOutputStream(), result);
    }
}

2. 在ResourceServerConfig中配置

@Configuration
@EnableResourceServer
public class ResourceServerConfig extends ResourceServerConfigurerAdapter {

    @Autowired
    private CustomAuthEntryPoint customAuthEntryPoint;

    @Override
    public void configure(HttpSecurity http) throws Exception {
        http
            .authorizeRequests()
                .anyRequest().authenticated() // 所有请求都需要认证
                .and()
            .exceptionHandling()
                .authenticationEntryPoint(customAuthEntryPoint); // 配置自定义的认证异常处理器
    }
}

方案二:额外配置AccessDeniedHandler处理权限不足异常

如果你的项目还需要处理AccessDeniedException(用户已认证但权限不足),可以再自定义一个AccessDeniedHandler,和上面的EntryPoint一起配置:

1. 实现自定义AccessDeniedHandler

@Component
public class CustomAccessDeniedHandler implements AccessDeniedHandler {

    @Override
    public void handle(HttpServletRequest request, 
                       HttpServletResponse response, 
                       AccessDeniedException accessDeniedException) throws IOException {
        response.setContentType("application/json;charset=UTF-8");
        response.setStatus(HttpServletResponse.SC_FORBIDDEN);
        
        Map<String, Object> result = new HashMap<>();
        result.put("code", 403);
        result.put("message", "权限不足:" + accessDeniedException.getMessage());
        result.put("timestamp", LocalDateTime.now().toString());
        
        ObjectMapper objectMapper = new ObjectMapper();
        objectMapper.writeValue(response.getOutputStream(), result);
    }
}

2. 更新ResourceServerConfig配置

@Configuration
@EnableResourceServer
public class ResourceServerConfig extends ResourceServerConfigurerAdapter {

    @Autowired
    private CustomAuthEntryPoint customAuthEntryPoint;
    @Autowired
    private CustomAccessDeniedHandler customAccessDeniedHandler;

    @Override
    public void configure(HttpSecurity http) throws Exception {
        http
            .authorizeRequests()
                .anyRequest().authenticated()
                .and()
            .exceptionHandling()
                .authenticationEntryPoint(customAuthEntryPoint)
                .accessDeniedHandler(customAccessDeniedHandler); // 新增权限不足处理器
    }
}

为什么这个方案可行?

因为AuthenticationEntryPoint和AccessDeniedHandler是Spring Security过滤器链层面的处理器,它们能直接捕获过滤器链中抛出的认证、权限相关异常,这正是@ControllerAdvice触及不到的区域,完美适配ResourceServer的场景。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.13 07:22:18