1. 为什么需要绕过自定义过滤器在SpringSecurity6的实际开发中我们经常会遇到这样的场景某些接口比如登录接口、健康检查接口明明已经配置了permitAll()但自定义的JWT过滤器还是会执行。这个问题困扰了不少开发者我自己在项目中也踩过这个坑。根本原因在于SpringSecurity的认证流程分为两个阶段认证和授权。permitAll()属于授权阶段的配置它只是告诉系统这个路径不需要权限但并不会阻止认证过滤器的执行。这就好比你去参加一个开放式讲座permitAll门口保安过滤器仍然会检查你的证件。更麻烦的是如果你的自定义过滤器被注册为Spring Bean它还会被自动加入到Servlet过滤器链中导致同一个请求会被过滤两次。我在项目初期就遇到过这个问题明明在Security配置中只添加了一次过滤器但日志显示每个请求都被处理了两次严重影响了性能。2. WebSecurityCustomizer的救赎之道2.1 ignoring()方法的魔力SpringSecurity6提供了WebSecurityCustomizer接口通过它的ignoring()方法可以实现真正的路径忽略。这个方法的效果相当于在安全防护体系上开了一个后门被忽略的路径会完全绕过SpringSecurity的所有处理流程。来看个典型配置示例Bean public WebSecurityCustomizer ignoringCustomizer() { return (web) - web.ignoring() .requestMatchers(/api/public/**, /healthcheck); }这段代码配置后/api/public/下的所有接口和/healthcheck接口将不执行任何Security过滤器包括自定义过滤器不进行CSRF防护不检查会话状态完全绕过认证授权流程2.2 与permitAll()的对比实验为了验证效果我做了组对比测试配置方式自定义过滤器执行CSRF检查会话管理适用场景permitAll()是是是需要安全检查的公开接口ignoring()否否否完全公开的静态资源实测发现对于登录接口这种真正需要完全放行的场景ignoring()才是最佳选择。比如微信小程序登录接口使用ignoring()后请求耗时直接从15ms降到了3ms因为跳过了所有安全校验环节。3. 实战配置指南3.1 基础配置步骤移除过滤器的Bean注解确保你的自定义过滤器没有被Component等注解标记避免被自动注册到Servlet过滤器链。在SecurityConfig中添加配置Configuration EnableWebSecurity public class SecurityConfig { // ...其他配置... Bean public WebSecurityCustomizer webSecurityCustomizer() { return (web) - web.ignoring() .requestMatchers( HttpMethod.POST, /auth/login, /v3/api-docs/**, /swagger-ui/** ); } }路径匹配的多种写法精确路径/auth/loginAnt风格/static/**正则表达式RegexRequestMatcher.regexMatcher(/public/.*)HTTP方法限定requestMatchers(HttpMethod.GET, /api/public)3.2 常见问题解决方案问题1忽略路径不生效检查顺序问题。我在项目中遇到过因为Filter注册顺序导致的异常后来通过调整配置类加载顺序解决Order(1) // 确保优先加载 Configuration public class SecurityConfig {...}问题2静态资源被拦截推荐这样配置return (web) - web.ignoring() .requestMatchers( /static/**, /favicon.ico, /robots.txt );问题3Swagger被拦截需要放行这些路径.requestMatchers( /v3/api-docs/**, /swagger-resources/**, /swagger-ui/**, /webjars/** )4. 深入原理剖析4.1 安全过滤器链的运作机制SpringSecurity的过滤器链就像机场的安检流程基础安检SecurityFilterChainX光机、金属探测门等标准设备VIP通道ignoring完全绕过所有安检普通通道permitAll仍然要走安检流程只是不需要登机牌WebSecurityCustomizer的配置会在过滤器链的最外层生效它通过WebSecurity的ignoring()方法创建了一个白名单这个名单中的请求会直接跳过整个Security过滤器链。4.2 源码关键点分析在WebSecurity类的源码中可以看到这样的逻辑public void ignoring() { this.ignoredRequests new IgnoredRequestConfigurer(); }被忽略的请求会被添加到ignoredRequests集合中后续在构建过滤器链时会优先检查当前请求是否在忽略列表中if (this.ignoredRequests ! null this.ignoredRequests.matches(request)) { chain.doFilter(request, response); return; }这就是为什么使用ignoring()配置的路径能完全绕过安全校验的根本原因。5. 最佳实践建议经过多个项目的实践验证我总结出以下经验分类处理不同公开接口前端静态资源使用ignoring()登录/注册接口使用ignoring()公开API如商品列表使用permitAll()生产环境推荐配置Bean public WebSecurityCustomizer webSecurityCustomizer() { return (web) - web.ignoring() .requestMatchers( /static/**, /assets/**, /auth/**, /actuator/health, /error ); }开发环境特殊处理Profile(dev) Bean public WebSecurityCustomizer devWebSecurityCustomizer() { return (web) - web.ignoring() .requestMatchers(/**); // 开发环境完全禁用安全校验 }性能优化技巧将高频访问的公开接口如健康检查放在ignoring()列表最前面使用AntPathRequestMatcher代替正则匹配性能更好避免在ignoring()中使用过于宽泛的路径匹配如/**在最近的一个电商项目中通过合理配置WebSecurityCustomizer系统QPS提升了约20%特别是促销期间的高并发场景下登录接口的响应时间保持稳定。