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

为何Spring抛出404异常却返回401状态码响应?

问题描述

我创建了一个新的Java Spring应用,并添加了一个包含单个方法的控制器:

@RestController
public class MyController {
    @GetMapping("/test")
    public String test() {
        throw new ResponseStatusException(HttpStatus.NOT_FOUND);
    }
}

当我发送GET /test请求时,收到无响应体的401状态码响应。但在Spring应用的标准输出中,我看到如下日志:

WARN 36 --- [nio-8080-exec-2] .w.s.m.a.ResponseStatusExceptionResolver : Resolved [org.springframework.web.server.ResponseStatusException: 404 NOT_FOUND]

请问为何会返回401而非预期的404?

原因分析与解决方案

这种矛盾现象的核心原因是请求的响应状态码被后续的拦截/过滤逻辑覆盖,最常见的场景和解决方法如下:

1. Spring Security 默认拦截(最普遍情况)

如果你的项目引入了spring-boot-starter-security依赖,Spring Security会默认对所有请求启用认证拦截:

  • 尽管日志显示控制器的404异常已被处理,但Security的过滤器链可能在后续环节修改了响应状态码;或者你的请求未通过认证,但因配置疏漏意外进入了控制器,最终Security强制将响应改为401。

解决方法:
在Security配置类中显式允许/test路径的匿名访问:

@Configuration
@EnableWebSecurity
public class SecurityConfig {
    @Bean
    public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {
        http.authorizeHttpRequests(authConfig -> authConfig
                .requestMatchers("/test").permitAll() // 放行/test路径,无需认证
                .anyRequest().authenticated()
        );
        return http.build();
    }
}

配置完成后,请求会正常到达控制器,返回预期的404状态码。

2. 自定义过滤器/拦截器修改响应状态码

如果项目中存在自定义的Filter或HandlerInterceptor,这些组件可能在ResponseStatusExceptionResolver处理完404异常后,重新修改了HttpServletResponse的状态码为401。

排查方法:

  • 检查项目中所有实现Filter接口或继承HandlerInterceptor的类,查看是否存在修改响应状态码的逻辑;
  • 临时禁用这些自定义组件,重新测试请求,验证是否恢复正常404响应。

3. 全局异常处理器配置错误

若项目中使用了@RestControllerAdvice实现全局异常处理,可能存在错误逻辑将ResponseStatusException(404)转换为401响应。

排查方法:
检查全局异常处理器的代码,确保没有错误映射404异常到401状态码的逻辑。


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.22 08:13:09