Spring Boot 3.4.0中Spring Security返回403问题的调整需求
问题分析
当前遇到两个核心问题:
- 未认证请求非白名单接口时,Spring Security默认返回403而非预期的401;
- 请求不存在的接口时,Security先拦截触发认证检查,返回403而非Spring MVC的404。
解决方案
1. 自定义未认证返回401
通过配置AuthenticationEntryPoint,覆盖Security默认的未认证处理逻辑,直接返回401状态码及自定义响应。
2. 让不存在的接口返回404
推荐两种实现方式:
- 方式一(简洁高效):限制Security仅拦截特定前缀的接口(如
/api/**),非该前缀的请求直接由Spring MVC处理,不存在时自然返回404; - 方式二(灵活适配):在
AuthenticationEntryPoint中判断请求是否存在对应的处理器,无处理器则返回404。
修改后的完整配置代码
@Configuration @RequiredArgsConstructor @EnableWebSecurity public class SecurityConfig { public static final String[] WHITE_LIST = { "/api/auth/**", "/api/public/**", "/v2/api-docs", "/swagger-resources/**", "/swagger-ui.html", "/hello" }; private static final Logger log = LoggerFactory.getLogger(SecurityConfig.class); @Bean public SecurityFilterChain securityFilterChain(HttpSecurity http, JwtFilter jwtFilter) throws Exception { http .csrf(AbstractHttpConfigurer::disable) // 仅拦截/api开头的请求,其他请求直接由Spring MVC处理 .securityMatcher("/api/**") .authorizeHttpRequests(auth -> { auth.requestMatchers(WHITE_LIST).permitAll(); auth.anyRequest().authenticated(); }) .sessionManagement(session -> session.sessionCreationPolicy(SessionCreationPolicy.STATELESS) ) .exceptionHandling(exception -> exception.authenticationEntryPoint((request, response, authException) -> { // 未认证时返回401及自定义JSON响应 response.setStatus(HttpServletResponse.SC_UNAUTHORIZED); response.setContentType(MediaType.APPLICATION_JSON_VALUE); String jsonResponse = "{\"code\":401,\"message\":\"未授权访问,请先登录\"}"; response.getWriter().write(jsonResponse); }) ) .addFilterBefore(jwtFilter, UsernamePasswordAuthenticationFilter.class); return http.build(); } @Bean public PasswordEncoder passwordEncoder() { log.info("Created Password Encoder"); return new BCryptPasswordEncoder(); } }
方式二(适配全路径场景)
如果你的接口没有统一前缀,可以用以下方式在AuthenticationEntryPoint中区分404和401:
.exceptionHandling(exception -> exception.authenticationEntryPoint((request, response, authException) -> { // 检查请求是否有对应的处理器 HandlerExecutionChain handler = request.getAttribute(DispatcherServlet.EXECUTION_CHAIN_ATTRIBUTE); if (handler == null || handler.getHandler() == null) { // 无处理器,返回404 response.setStatus(HttpServletResponse.SC_NOT_FOUND); response.setContentType(MediaType.APPLICATION_JSON_VALUE); String jsonResponse = "{\"code\":404,\"message\":\"接口不存在\"}"; response.getWriter().write(jsonResponse); } else { // 有处理器但未认证,返回401 response.setStatus(HttpServletResponse.SC_UNAUTHORIZED); response.setContentType(MediaType.APPLICATION_JSON_VALUE); String jsonResponse = "{\"code\":401,\"message\":\"未授权访问,请先登录\"}"; response.getWriter().write(jsonResponse); } }) )
内容的提问来源于stack exchange,提问作者Nguyen Manh Cuong
相关产品推荐
相关产品推荐

