Spring Security调用不存在端点返回403而非404如何解决?
问题原因
Spring Security的过滤器执行优先级远高于Spring MVC的请求映射匹配逻辑。你当前配置的anyRequest().authenticated()会对所有进入容器的请求先做权限校验,只要用户未登录/无权限,直接返回403,请求根本不会走到Spring MVC层去判断端点是否存在,所以不会触发404。
方案1:显式声明需要保护的路径范围,不使用anyRequest()匹配所有路径
如果项目路径规范,所有需要保护的接口都有统一前缀,推荐用这个方案,实现最简单:只对明确的业务路径前缀做权限校验,未匹配到的路径直接放通,走Spring MVC正常的404逻辑即可。
@Override protected void configure(HttpSecurity http) throws Exception { http.csrf().and().cors().disable(); http.sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS); http.authorizeRequests() // 公开接口放行 .antMatchers("/login", "/api/v1/auth/**").permitAll() // 只对业务接口路径做认证要求,可根据实际业务前缀调整 .antMatchers("/api/v1/**").authenticated(); // 移除anyRequest().authenticated()配置,其余路径直接放通走MVC逻辑 }
方案2:自定义异常处理器,无权限时先判断端点是否存在
如果项目路径分散,没办法用前缀统一匹配,可以自定义认证入口和权限拒绝处理器,在返回异常前先判断请求路径是否存在对应的端点。
- 首先自定义两个异常处理器:
@Component public class CustomAuthenticationEntryPoint implements AuthenticationEntryPoint { @Autowired private HandlerMapping handlerMapping; @Override public void commence(HttpServletRequest request, HttpServletResponse response, AuthenticationException authException) throws IOException, ServletException { try { // 检查是否存在对应的请求映射 handlerMapping.getHandler(request); // 存在对应端点,返回401未认证 response.sendError(HttpServletResponse.SC_UNAUTHORIZED, authException.getMessage()); } catch (NoHandlerFoundException e) { // 不存在对应端点,返回404 response.sendError(HttpServletResponse.SC_NOT_FOUND, "资源不存在"); } } }
@Component public class CustomAccessDeniedHandler implements AccessDeniedHandler { @Autowired private HandlerMapping handlerMapping; @Override public void handle(HttpServletRequest request, HttpServletResponse response, AccessDeniedException accessDeniedException) throws IOException, ServletException { try { handlerMapping.getHandler(request); response.sendError(HttpServletResponse.SC_FORBIDDEN, accessDeniedException.getMessage()); } catch (NoHandlerFoundException e) { response.sendError(HttpServletResponse.SC_NOT_FOUND, "资源不存在"); } } }
- 在Spring MVC配置中开启找不到处理器时抛异常的开关:
# application.yml配置 spring: mvc: throw-exception-if-no-handler-found: true web: resources: add-mappings: false # 若后端需要托管静态资源可删除此配置,按需调整匹配规则即可
- 把自定义处理器配置到Spring Security规则中:
@Override protected void configure(HttpSecurity http) throws Exception { http.csrf().and().cors().disable(); http.sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS); http.authorizeRequests() .antMatchers("/login", "/api/v1/auth/**").permitAll() .anyRequest().authenticated(); // 注册自定义异常处理器 http.exceptionHandling() .authenticationEntryPoint(customAuthenticationEntryPoint) .accessDeniedHandler(customAccessDeniedHandler); }
内容的提问来源于stack exchange,提问作者Avaldor
相关产品推荐
相关产品推荐

