Spring Security问题:访问不存在端点触发AuthenticationEntryPoint,如何返回404?
解决方案:访问不存在端点时返回404而非触发AuthenticationEntryPoint
问题根源在于Spring Security的anyRequest().authenticated()会优先拦截所有请求做认证校验,哪怕请求的端点根本不存在。这种情况下,认证流程先于Spring MVC的404判定执行,导致AuthenticationEntryPoint被触发。
可以通过两种方式解决:
方式一:调整拦截顺序,优先放行错误请求
修改SecurityFilterChain配置,添加对DispatcherType.ERROR的放行规则,让Spring MVC先处理不存在的端点请求:
@Bean public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception { return http .cors().and() .csrf().disable() .exceptionHandling() .authenticationEntryPoint(customAuthenticationEntryPoint()).and() .sessionManagement() .sessionCreationPolicy(SessionCreationPolicy.STATELESS).and() .authorizeHttpRequests(auth -> auth .dispatcherTypeMatchers(DispatcherType.ERROR).permitAll() // 允许处理错误类请求 .requestMatchers("/api/auth/**").permitAll() .anyRequest().authenticated()) .addFilterBefore(jwtTokenFilter, UsernamePasswordAuthenticationFilter.class) .build(); }
方式二:在自定义AuthenticationEntryPoint中判断端点是否存在
在你的customAuthenticationEntryPoint里,检查请求是否匹配已定义的端点,不匹配则直接返回404:
@Component public class CustomAuthenticationEntryPoint implements AuthenticationEntryPoint { @Autowired private RequestMappingHandlerMapping requestMappingHandlerMapping; @Override public void commence(HttpServletRequest request, HttpServletResponse response, AuthenticationException authException) throws IOException, ServletException { try { // 检查请求是否对应已存在的端点 HandlerExecutionChain handlerChain = requestMappingHandlerMapping.getHandler(request); if (handlerChain == null) { // 无匹配端点,返回404 response.sendError(HttpServletResponse.SC_NOT_FOUND, "资源不存在"); return; } } catch (Exception e) { // 出现异常时走默认认证失败逻辑 } // 有匹配端点但认证失败,执行原有认证失败处理 response.sendError(HttpServletResponse.SC_UNAUTHORIZED, "认证失败"); } }
补充说明
第一种方式更简洁,利用Spring Security的分发类型匹配,让404请求直接绕过认证拦截;第二种方式灵活性更高,适合需要在认证入口做更多自定义判断的场景。
内容的提问来源于stack exchange,提问作者Ilya Avkhimenya
相关产品推荐
相关产品推荐

