Spring Security:如何让过滤器忽略WebSecurity配置的忽略URL?
这个问题我之前也碰到过,核心原因在于WebSecurity的ignoring()规则和HttpSecurity中添加的过滤器的作用范围不是完全绑定的——或者说,你可能误解了web.ignoring()的生效逻辑,或者过滤器的注册方式导致它不受忽略规则约束。
先理清楚底层逻辑:web.ignoring()的作用是让匹配的请求完全跳过Spring Security的整个过滤器链,包括你通过addFilterAfter添加到HttpSecurity里的过滤器。如果你的忽略URL还是被过滤器处理了,大概率是下面两种情况之一:
- 你的正则匹配规则写得有问题,请求其实没被WebSecurity正确忽略;
- 过滤器的注册方式脱离了Spring Security的过滤器链(比如直接用
@WebFilter或FilterRegistrationBean注册到Servlet容器),这种情况下它不受Spring Security的忽略规则管控。
针对不同情况,这里有几种靠谱的解决方案:
方案一:在自定义过滤器中手动跳过忽略URL
这是最直接的方式,复用你原来的正则规则,在过滤器里判断请求是否属于忽略范围,是的话直接放行不处理。
修改你的MyFilter类,重写shouldNotFilter方法:
public class MyFilter extends OncePerRequestFilter { // 复用WebSecurity里的正则规则 private static final Pattern IGNORED_URL_PATTERN = Pattern.compile("a regex pattern here"); @Override protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) throws ServletException, IOException { // 你的核心过滤逻辑写在这里 filterChain.doFilter(request, response); } @Override protected boolean shouldNotFilter(HttpServletRequest request) throws ServletException { String requestMethod = request.getMethod(); String requestUri = request.getRequestURI(); // 判断是否是POST请求且匹配忽略的URL正则 return HttpMethod.POST.name().equalsIgnoreCase(requestMethod) && IGNORED_URL_PATTERN.matcher(requestUri).matches(); } }
这个方法是OncePerRequestFilter提供的钩子,返回true时过滤器会跳过当前请求,完全符合你的需求。
方案二:通过HttpSecurity限制过滤器的作用范围
如果你的过滤器是通过HttpSecurity.addFilterAfter添加的,可以用NegatedRequestMatcher来反转忽略规则,让过滤器只对非忽略的URL生效:
@Override protected void configure(HttpSecurity http) throws Exception { // 定义你要忽略的请求匹配器 RequestMatcher ignoredMatcher = new RegexRequestMatcher("a regex pattern here", HttpMethod.POST.name()); http // 让过滤器只作用于非忽略的请求 .requestMatcher(new NegatedRequestMatcher(ignoredMatcher)) .addFilterAfter(myFilter, AbstractPreAuthenticatedProcessingFilter.class) // 其他Spring Security配置... // 单独配置忽略URL的授权(允许匿名访问) .and() .requestMatcher(ignoredMatcher) .authorizeRequests() .anyRequest().permitAll(); }
这种方式把忽略规则和过滤器的作用范围绑定在一起,避免重复写正则规则。
方案三:如果是Servlet级过滤器,直接排除URL
如果你是用FilterRegistrationBean或@WebFilter把过滤器注册到Servlet容器的(不是通过HttpSecurity添加),可以直接在注册时排除忽略的URL:
@Bean public FilterRegistrationBean<MyFilter> myFilterRegistration(MyFilter myFilter) { FilterRegistrationBean<MyFilter> registrationBean = new FilterRegistrationBean<>(); registrationBean.setFilter(myFilter); registrationBean.addUrlPatterns("/**"); // 匹配所有URL // 排除你要忽略的正则URL registrationBean.addExcludeUrlPatterns("a regex pattern here"); return registrationBean; }
注意这种方式是Servlet容器层面的过滤,和Spring Security的过滤器链是独立的,所以必须手动排除。
最后建议先检查你的正则匹配是否正确——比如用日志打印请求的URL和方法,确认是否真的匹配web.ignoring()里的规则,很多时候问题出在这里。
内容的提问来源于stack exchange,提问作者Sasha Shpota




