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

为什么Spring Security未按配置返回403,实际返回405响应状态?

问题根因

从日志可以明确问题产生的流程:

  • 访问VERIFY_BADGE_URL时,DelegatingAuthenticationEntryPoint正确匹配到Http403ForbiddenEntryPoint,写入403响应状态
  • Spring Boot默认开启错误页自动转发规则,状态码>=400的响应会被服务器转发到/error路径做统一错误处理,原请求为POST方法,转发后的请求也为POST方法
  • 你的项目中/error路径对应的处理器不支持POST方法,触发HttpRequestMethodNotSupportedException,最终返回405状态码

解决方案

方案1:禁用错误页转发(推荐,符合接口直接返回状态码的需求)

在configure方法的exceptionHandling配置中,补充配置AccessDeniedHandler,同时直接在响应写入状态码后禁止后续转发:

@Override
protected void configure(HttpSecurity http) throws Exception {
    http.csrf().disable();

    // 你原有的EntryPoint映射配置保持不变
    LinkedHashMap<RequestMatcher, AuthenticationEntryPoint> map = new LinkedHashMap<>();
    // ... 原有map.put配置不变

    http.authorizeRequests()
            // 原有权限规则不变
            .antMatchers(WELCOME_PAGE,
                    FOOD_SELECTION_PAGE + "/**",
                    CHECKOUT_URL,
                    VERIFY_BADGE_URL,
                    VERIFY_NAME_URL).denyAll()
            .antMatchers(ADMIN_PAGE,
                    NEW_FOOD_PAGE,
                    EDIT_FOOD_URL + "/**",
                    HIDE_FOOD_URL,
                    SHOW_FOOD_URL,
                    DELETE_FOOD_URL,
                    REFRESH_EMPS_URL).hasAnyAuthority("ROLES_USER")
            .anyRequest().permitAll()
            .and().formLogin().loginPage(LOGIN_PAGE)
                .usernameParameter("username")
                .passwordParameter("pin")
                .defaultSuccessUrl(ADMIN_PAGE)
                .permitAll()
                .failureUrl(LOGIN_PAGE + "?badlogin")
            .and().exceptionHandling()
                .authenticationEntryPoint(new DelegatingAuthenticationEntryPoint(map))
                // 新增AccessDeniedHandler配置,处理已认证用户权限不足的场景,直接返回403
                .accessDeniedHandler((request, response, accessDeniedException) -> {
                    response.setStatus(HttpServletResponse.SC_FORBIDDEN);
                    response.getWriter().flush();
                });
}

如果仍有转发问题,可在配置文件application.properties中添加如下配置关闭默认错误页:

server.error.whitelabel.enabled=false

方案2:兼容/error路径POST请求

如果需要保留项目全局错误处理逻辑,直接自定义ErrorController,添加POST方法的支持即可:

@RestController
public class CustomErrorController implements ErrorController {
    @RequestMapping(value = "/error", method = {RequestMethod.GET, RequestMethod.POST})
    public ResponseEntity<Map<String, Object>> handleError(HttpServletRequest request) {
        Integer statusCode = (Integer) request.getAttribute("javax.servlet.error.status_code");
        Map<String, Object> error = new HashMap<>();
        error.put("code", statusCode);
        error.put("message", request.getAttribute("javax.servlet.error.message"));
        return ResponseEntity.status(statusCode).body(error);
    }
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.07 10:57:03