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

Spring Security中ControllerAdvice致AccessDeniedHandler未调用

根因说明

这个问题来自Spring Security异常处理的作用域边界:

  1. 配置在HttpSecurity中的AccessDeniedHandler仅由过滤器链中的ExceptionTranslationFilter触发,只处理过滤器链执行阶段产生的权限异常,比如URL规则匹配后判定权限不足的场景。
  2. @EnableGlobalMethodSecurity开启的方法级校验(@PreAuthorize/@PostAuthorize等)基于Spring AOP实现,拦截点在Controller方法调用阶段,这一层抛出的AccessDeniedException会直接进入Spring MVC的异常分发流程,被@ControllerAdvice的@ExceptionHandler优先捕获,根本不会回传到过滤器链,自然触发不到你配置的AccessDeniedHandler。
  3. AccessDeniedException继承自RuntimeException,因此会被你定义的通用RuntimeException全局处理器兜底,错误返回500状态码。
解决方法

不需要修改现有RuntimeException全局处理逻辑,选下面最简便的方案即可:

推荐方案:在ControllerAdvice中新增AccessDeniedException专属处理方法

Spring MVC的异常匹配规则会优先命中类型更具体的@ExceptionHandler,你只需要在现有全局异常类中注入自定义的AccessDeniedHandler,新增一个专门处理AccessDeniedException的方法,直接复用已有Handler的逻辑即可,不会影响原有RuntimeException的处理。
代码示例:

// 注入你已经实现好的自定义AccessDeniedHandler
@Autowired
private ThingspodAccessDeniedHandler accessDeniedHandler;

@ExceptionHandler(AccessDeniedException.class)
public void handleMethodLevelAccessDenied(AccessDeniedException ex, 
                                          HttpServletRequest request, 
                                          HttpServletResponse response) throws IOException {
    // 直接调用已有Handler逻辑,保证所有权限拒绝场景的响应格式完全统一
    accessDeniedHandler.handle(request, response, ex);
}

// 原有RuntimeException全局处理逻辑完全保留,不需要做任何修改
@ExceptionHandler(RuntimeException.class)
public ResponseEntity<Object> handleAllUncaughtRuntimeException(
        RuntimeException ex, WebRequest request){
    return buildApiErrorResponse(ex, HttpStatus.INTERNAL_SERVER_ERROR, ThingspodErrorCode.GENERAL, request);
}

可选配置优化

你当前的Security配置中重复调用了两次exceptionHandling(),虽然不会造成功能异常,但可以合并简化,避免冗余配置:

@Override
protected void configure(HttpSecurity http) throws Exception {
    http.headers().cacheControl().and().frameOptions().disable()
            .and()
            .cors()
            .and()
            .csrf().disable()
            .exceptionHandling()
                // 把accessDeniedHandler配置统一放在exceptionHandling块下
                .accessDeniedHandler(accessDeniedHandler)
            .and()
            .sessionManagement()
                .sessionCreationPolicy(SessionCreationPolicy.STATELESS)
            .and()
            .authorizeRequests()
                .antMatchers(paymentCallbackPath).permitAll()
                .antMatchers(TOKEN_BASED_AUTH_ENTRY_POINT).authenticated()
            .and()
            .addFilterBefore(jwtAuthenticationFilter(), UsernamePasswordAuthenticationFilter.class);
}

不推荐通过重写GlobalMethodSecurityConfiguration的方式透传异常,配置复杂度高,后续版本升级兼容性差,没有必要。


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.29 19:15:47