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

Spring Boot 3.2.0全局API异常处理器未生效,Tomcat错误页处理报错,如何禁用错误页处理?

Spring Boot 3.2.0全局API异常处理器未生效,Tomcat错误页处理报错,如何禁用错误页处理?

看起来你遇到的核心问题是Spring Security过滤器链中抛出的异常没被@ControllerAdvice捕获,反而触发了Tomcat的错误页转发机制,导致出现Exception Processing ErrorPage的报错。下面我给你一步步拆解解决思路:

一、为什么全局异常处理器没生效?

你的UnauthorizedAccessException是在ApiKeyAuthFilter这个Spring Security过滤器里抛出的,而@ControllerAdvice只能处理**Controller层(DispatcherServlet之后)**抛出的异常。过滤器链的异常发生在DispatcherServlet之前,根本到不了你的全局异常处理器,反而会被Tomcat的错误页机制接管,尝试转发到/error端点,这就是你看到报错的原因。

二、解决方案步骤

1. 用Spring Security的AuthenticationEntryPoint处理过滤器层异常

我们需要让Spring Security自己接管认证异常的处理,而不是交给Tomcat。先创建一个自定义的认证入口点:

import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import org.springframework.http.MediaType;
import org.springframework.security.core.AuthenticationException;
import org.springframework.security.web.AuthenticationEntryPoint;
import com.fasterxml.jackson.databind.ObjectMapper;
import rs.yettel.roamingbarring.exception.UnauthorizedAccessException;
import rs.yettel.roamingbarring.model.ApiResponseWrapper;
import rs.yettel.roamingbarring.model.ApiErrorResponse;
import org.springframework.http.HttpStatus;

public class CustomAuthenticationEntryPoint implements AuthenticationEntryPoint {

    private static final String API_ID_CODE = "你的API_ID_CODE值";
    private final ObjectMapper objectMapper = new ObjectMapper();

    @Override
    public void commence(HttpServletRequest request, HttpServletResponse response, AuthenticationException authException) throws IOException {
        // 针对性处理我们自定义的UnauthorizedAccessException
        if (authException.getCause() instanceof UnauthorizedAccessException ex) {
            response.setStatus(HttpServletResponse.SC_UNAUTHORIZED);
            response.setContentType(MediaType.APPLICATION_JSON_VALUE);
            
            // 构建自定义的错误响应体
            ApiResponseWrapper errorResponse = new ApiResponseWrapper(
                new ApiErrorResponse(
                    HttpStatus.UNAUTHORIZED.value() + "." + API_ID_CODE + "." + ex.getErrorType().getCode(),
                    ex.getErrorType().getMessage()
                )
            );
            
            objectMapper.writeValue(response.getWriter(), errorResponse);
        } else {
            // 兜底处理其他认证异常
            response.setStatus(HttpServletResponse.SC_UNAUTHORIZED);
            response.setContentType(MediaType.APPLICATION_JSON_VALUE);
            objectMapper.writeValue(response.getWriter(), 
                new ApiResponseWrapper(new ApiErrorResponse("401.xxx.001", "未授权访问")));
        }
    }
}

然后在你的Security配置类中注册这个入口点:

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.web.SecurityFilterChain;
import org.springframework.security.web.authentication.preauth.AbstractPreAuthenticatedProcessingFilter;

@Configuration
@EnableWebSecurity
public class SecurityConfig {

    private final ApiKeyAuthFilter apiKeyAuthFilter;

    public SecurityConfig(ApiKeyAuthFilter apiKeyAuthFilter) {
        this.apiKeyAuthFilter = apiKeyAuthFilter;
    }

    @Bean
    public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {
        http
            .csrf(csrf -> csrf.disable())
            .authorizeHttpRequests(auth -> auth
                .anyRequest().authenticated()
            )
            .addFilterBefore(apiKeyAuthFilter, AbstractPreAuthenticatedProcessingFilter.class)
            // 配置自定义认证入口点,接管过滤器层异常
            .exceptionHandling(ex -> ex
                .authenticationEntryPoint(new CustomAuthenticationEntryPoint())
            );
        
        return http.build();
    }
}

2. 禁用Tomcat错误页转发机制

为了彻底避免Tomcat触发错误页处理,在Spring Boot配置文件中添加以下设置:

application.properties:

# 禁用默认的白标错误页,避免Tomcat转发到/error
server.error.whitelabel.enabled=false

application.yml:

server:
  error:
    whitelabel:
      enabled: false

三、额外检查点

  • 确认你的ApiKeyAuthFilter中抛出的异常正确传递给了Spring Security(比如可以用throw new AuthenticationException("xxx", ex)包装你的自定义异常)
  • 验证@ControllerAdvice本身是正常工作的(可以在Controller层手动抛出一个UnauthorizedAccessException测试)

这样调整后,当没有Bearer token时,就能返回你自定义的ApiResponseWrapper响应,不会再出现Tomcat的错误页处理报错了。

备注:内容来源于stack exchange,提问作者Dobrosav Vlaskovic

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.04.20 11:18:07