Spring Boot中用Filter转发请求及解决CAS认证跳转循环问题
解决Spring Boot中跳过CAS认证的Filter无限循环问题
看起来你遇到的问题是Spring Boot和Spring MVC在Filter处理逻辑上的差异导致的——**当你对/api/路径的POST请求做forward转发时,这个转发后的内部请求会再次被你的自定义Filter拦截,从而陷入无限循环。而Spring MVC环境下可能默认限制了Filter只处理外部请求,所以没这个问题。
下面给你两个最有效的解决思路,结合代码示例来说明:
思路1:限制Filter仅处理外部请求(最推荐)
Spring Boot中,FilterRegistrationBean默认会让Filter处理所有类型的请求(包括FORWARD、INCLUDE这类内部调度请求)。你只需要指定Filter仅处理外部的REQUEST类型请求,就能避免转发后的请求再次被拦截:
@Configuration public class WebApiConfig { @Bean public FilterRegistrationBean<SkipCasFilter> testFilterRegistration() { FilterRegistrationBean<SkipCasFilter> registration = new FilterRegistrationBean<>(); registration.setFilter(new SkipCasFilter()); registration.addUrlPatterns("/api/**"); // 关键:只处理外部发起的请求,忽略内部forward的请求 registration.setDispatcherTypes(DispatcherType.REQUEST); // 设置优先级高于CAS Filter,确保先执行 registration.setOrder(Ordered.HIGHEST_PRECEDENCE); return registration; } // 你的自定义Filter public static class SkipCasFilter implements Filter { @Override public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException { // 直接放行给后续控制器,无需forward(forward反而会触发内部请求) chain.doFilter(request, response); } } }
这里我把原来的forward改成了直接调用chain.doFilter——因为你的目标本来就是让/api/**跳过CAS认证直接到控制器,没必要做转发,直接放行更简洁。
思路2:标记请求已处理,避免重复拦截
如果因为某些原因必须保留forward逻辑,可以在请求中设置一个标记属性,Filter每次拦截时先检查这个标记,已处理过就直接放行:
public static class SkipCasFilter implements Filter { private static final String PROCESSED_MARK = "SKIP_CAS_PROCESSED"; @Override public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException { // 检查是否已经处理过这个请求,避免循环 if (request.getAttribute(PROCESSED_MARK) != null) { chain.doFilter(request, response); return; } HttpServletRequest httpRequest = (HttpServletRequest) request; String uri = httpRequest.getRequestURI(); if (uri.startsWith("/api/")) { // 标记请求已处理 request.setAttribute(PROCESSED_MARK, true); // 转发到目标路径 request.getRequestDispatcher(uri).forward(request, response); } else { chain.doFilter(request, response); } } }
额外建议:调整CAS Filter的排除规则
其实更优雅的方式是直接让CAS Filter本身跳过/api/**路径,这样你甚至不需要写自定义Filter。比如如果你用的是Spring Security集成CAS,可以在配置中添加:
@Configuration @EnableWebSecurity public class SecurityConfig extends WebSecurityConfigurerAdapter { @Override protected void configure(HttpSecurity http) throws Exception { http .authorizeRequests() .antMatchers("/api/**").permitAll() // 允许/api/**无需认证 .anyRequest().authenticated() .and() .casAuthentication(); // 你的CAS配置 } }
这种方式从根源上避免了Filter拦截冲突,推荐优先考虑。
内容的提问来源于stack exchange,提问作者felix1982
相关产品推荐
相关产品推荐

