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

Spring Boot接口返回403而非405 Method Not Allowed问题修复

解决Spring Boot接口返回403而非405的问题

问题根源在于Spring Security的CSRF过滤器执行优先级高于Spring MVC的请求方法校验:当启用CSRF保护时,POST请求会先被Security拦截检查令牌,若令牌缺失直接返回403,根本没机会进入MVC环节判断请求方法是否允许,因此看不到预期的405。

以下是两种可行的解决思路:

方案一:对特定接口忽略CSRF检查

如果你的接口是纯后端调用(无需浏览器端CSRF保护),可以直接在Security配置中跳过指定路径的CSRF校验,让MVC的方法校验优先执行:

@Configuration
public class ApiSecurityConfig {

    @Bean
    public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
        http
            // 保留你的其他安全配置(如认证、授权规则)
            .authorizeHttpRequests(auth -> auth
                .anyRequest().authenticated()
            )
            .csrf(csrf -> csrf
                // 忽略不需要CSRF保护的接口路径,支持Ant风格匹配
                .ignoringRequestMatchers("/api/public/**", "/api/third-party/**")
            )
            .exceptionHandling(ex -> ex
                .authenticationEntryPoint(new CustomAuthenticationEntryPoint())
            );
        return http.build();
    }
}

配置后,这些被忽略的接口在收到不支持的请求方法时,会直接返回405而非403。

方案二:添加前置过滤器优先校验请求方法

如果所有接口都需要CSRF保护,可自定义一个过滤器放在CSRF过滤器之前,先检查当前请求的路径是否支持对应的HTTP方法,不支持则直接返回405:

1. 实现自定义方法校验过滤器

@Component
public class RequestMethodValidationFilter extends OncePerRequestFilter {

    private final RequestMappingHandlerMapping requestMappingHandlerMapping;
    private final PathMatcher pathMatcher = new AntPathMatcher();

    public RequestMethodValidationFilter(RequestMappingHandlerMapping requestMappingHandlerMapping) {
        this.requestMappingHandlerMapping = requestMappingHandlerMapping;
    }

    @Override
    protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) throws ServletException, IOException {
        String requestUri = request.getRequestURI();
        String requestMethod = request.getMethod();

        try {
            // 查找当前路径对应的所有支持的HTTP方法
            Set<String> allowedMethods = requestMappingHandlerMapping.getHandlerMethods().entrySet().stream()
                    .filter(entry -> entry.getKey().getPatternsCondition().getPatterns().stream()
                            .anyMatch(pattern -> pathMatcher.match(pattern, requestUri)))
                    .flatMap(entry -> entry.getKey().getMethodsCondition().getMethods().stream())
                    .map(HttpMethod::name)
                    .collect(Collectors.toSet());

            // 如果请求方法不在允许范围内,直接返回405
            if (!allowedMethods.isEmpty() && !allowedMethods.contains(requestMethod)) {
                response.setStatus(HttpServletResponse.SC_METHOD_NOT_ALLOWED);
                response.setContentType(MediaType.APPLICATION_JSON_VALUE);
                // 可根据你的全局异常格式自定义返回内容
                response.getWriter().write("{\"code\":405,\"message\":\"不支持的请求方法,允许的方法:" + String.join(",", allowedMethods) + "\"}");
                return;
            }
        } catch (Exception e) {
            // 异常时放行,继续执行后续过滤器
            filterChain.doFilter(request, response);
            return;
        }

        // 方法合法,继续执行CSRF等后续过滤器
        filterChain.doFilter(request, response);
    }
}

2. 在Security配置中注册前置过滤器

@Configuration
public class ApiSecurityConfig {

    @Bean
    public SecurityFilterChain filterChain(HttpSecurity http, RequestMethodValidationFilter methodValidationFilter) throws Exception {
        http
            // 将自定义过滤器放在CSRF过滤器之前
            .addFilterBefore(methodValidationFilter, CsrfFilter.class)
            // 保留原有安全配置
            .authorizeHttpRequests(auth -> auth
                .anyRequest().authenticated()
            )
            .csrf(csrf -> csrf
                // 保留你的CSRF配置(如令牌存储、请求头设置)
            )
            .exceptionHandling(ex -> ex
                .authenticationEntryPoint(new CustomAuthenticationEntryPoint())
            );
        return http.build();
    }
}

额外注意事项

如果接口本身支持POST方法,只是测试时忘记携带CSRF令牌,此时返回403是正常的。Postman测试时需:

  1. 先发送GET请求获取Cookie中的XSRF-TOKEN值;
  2. 在POST请求的请求头中添加X-XSRF-TOKEN,值为获取到的令牌内容。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.29 11:38:15