Spring Boot自定义过滤器致仅匹配"/",接口返回404问题求助
核心问题分析
1. 自定义BasicFilter的RequestMatcher配置逻辑错误
你在SecurityConfig中创建BasicFilter时,错误使用了RouteMatchHelper.combination()方法:
RouteMatchHelper.combination( RouteMatchHelper.orRoutes( "/api/**" ), RouteMatchHelper.orRoutes( "/actuator/health" ) )
查看combination方法的实现,它会生成一个AndRequestMatcher,逻辑是:匹配第一个路径集合(/api/**)并且不匹配第二个路径集合(/actuator/health)。这完全不符合你的预期——你原本想让BasicFilter作用于/api/**和/actuator/health所有路径,结果变成了只作用于/api/**且排除/actuator/health,导致请求处理逻辑混乱。
2. AbstractAuthenticationProcessingFilter默认行为导致请求重定向
BasicFilter继承自AbstractAuthenticationProcessingFilter,该过滤器默认使用SavedRequestAwareAuthenticationSuccessHandler,认证成功后会自动重定向到“保存的请求路径”(通常是根路径/),这就解释了为什么日志中记录的请求路径是/,而实际请求的/api/user/login被重定向后找不到对应控制器,返回404。
3. 请求日志拦截器的路径截取逻辑错误
RequestLoggingInterceptor中的extractPath方法实现存在缺陷:
private String extractPath( final HttpServletRequest request ) { final String path = request.getRequestURI().toString(); return path.substring( path.indexOf( "/", 1 ) ); }
当请求URI为/api/user/login时,path.indexOf("/",1)会找到第二个/的索引位置(3),截取后得到/user/login;如果请求URI是根路径/,indexOf("/",1)返回-1,调用substring(-1)会抛出异常,而日志中显示路径为/,说明该方法在异常场景下的处理(可能被捕获但未正确处理)导致日志记录错误路径。
解决方法
1. 修正BasicFilter的RequestMatcher配置
直接使用RouteMatchHelper.orRoutes()组合需要BasicFilter处理的所有路径,替换原本的combination调用:
final BasicFilter basicFilter = new BasicFilter( RouteMatchHelper.orRoutes( "/api/**", "/actuator/health" ), authenticationManager(), restProperties );
2. 覆盖AbstractAuthenticationProcessingFilter的默认成功/失败处理器
在BasicFilter的构造方法中,配置自定义的认证成功/失败处理器,避免重定向,让请求继续向下传递到控制器:
public BasicFilter(RequestMatcher requiresAuthenticationRequestMatcher, AuthenticationManager authenticationManager, RestProperties restProperties) { super(requiresAuthenticationRequestMatcher, authenticationManager); this.restProperties = restProperties; // 认证成功后不重定向,继续处理请求 SimpleUrlAuthenticationSuccessHandler successHandler = new SimpleUrlAuthenticationSuccessHandler(); successHandler.setRedirectStrategy((request, response, url) -> {}); setAuthenticationSuccessHandler(successHandler); // 认证失败时直接返回401状态码 setAuthenticationFailureHandler((request, response, exception) -> { response.sendError(HttpServletResponse.SC_UNAUTHORIZED, exception.getMessage()); }); }
3. 修复请求日志拦截器的路径截取逻辑
修改extractPath方法,正确处理上下文路径和请求URI的关系,避免错误截取:
private String extractPath( final HttpServletRequest request ) { String contextPath = request.getContextPath(); String uri = request.getRequestURI(); // 去掉上下文路径,保留相对路径 if (StringUtils.isNotEmpty(contextPath) && uri.startsWith(contextPath)) { return uri.substring(contextPath.length()); } return uri; }
注意:需要引入org.springframework.util.StringUtils工具类,或者自行实现空字符串判断逻辑。
内容的提问来源于stack exchange,提问作者Daniel Stieglmayr

