Spring Security 6.1.1未映射API路由返回403而非404问题排查
Spring Security 6.1.1 + JWT:未映射路由返回403而非404的问题排查与解决
问题根源
Spring Security 6.x默认会将未匹配到任何控制器路由的请求转发到内置的/error端点,这个转发请求会二次触发Security Filter Chain执行。第一次请求时你的JWT认证成功,但转发到/error时,要么请求头中的JWT令牌未被携带到转发请求中,要么/error端点的权限配置未允许匿名访问,导致二次请求被判定为匿名认证,触发AccessDeniedException返回403。
具体解决方法
1. 放行/error端点的匿名访问
在SecurityFilterChain配置中,明确允许匿名访问/error端点,确保转发请求能正常返回404错误:
@Bean public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception { http .csrf(csrf -> csrf.disable()) .authorizeHttpRequests(auth -> auth .requestMatchers("/auth/**").permitAll() .requestMatchers("/error").permitAll() // 新增该行放行error端点 .anyRequest().authenticated() ) .addFilterBefore(jwtTokenFilter, UsernamePasswordAuthenticationFilter.class); return http.build(); }
2. 确保JwtTokenFilter处理转发请求
检查自定义JwtTokenFilter的doFilter方法是否覆盖了转发场景:
- 避免仅匹配特定前缀的URI,确保所有请求(包括转发的
/error请求)都能经过令牌校验 - 确认Filter被正确添加到Security Filter Chain的前置位置(如
UsernamePasswordAuthenticationFilter之前),保证认证逻辑优先执行
3. 禁用转发错误处理,直接返回404
如果不想依赖内置/error端点,可配置DispatcherServlet直接抛出无处理器异常,再通过全局异常处理器返回404:
// WebMvc配置类 @Configuration public class WebConfig implements WebMvcConfigurer { @Bean public DispatcherServlet dispatcherServlet() { DispatcherServlet servlet = new DispatcherServlet(); // 无匹配处理器时直接抛出异常 servlet.setThrowExceptionIfNoHandlerFound(true); return servlet; } } // 全局异常处理器 @RestControllerAdvice public class GlobalExceptionHandler { @ExceptionHandler(NoHandlerFoundException.class) public ResponseEntity<String> handleNotFound(NoHandlerFoundException ex) { return ResponseEntity.status(HttpStatus.NOT_FOUND).body("Resource not found"); } }
这种方式避免了二次FilterChain执行,直接返回预期的404响应。
4. 排查重复FilterChain注册
检查项目中是否存在多个SecurityFilterChain Bean,或通过@Order注解明确FilterChain的优先级,避免重复执行认证逻辑。
内容的提问来源于stack exchange,提问作者Bruno Paiva
相关产品推荐
相关产品推荐

