Spring Boot 1.5.8自定义Servlet注册与Spring Security XML配置冲突问题
嘿,我来帮你搞定这个Spring Security的过滤器链顺序问题!
错误原因分析
你遇到的错误提示非常明确:
A universal match pattern ('/**') is defined before other patterns in the filter chain, causing them to be ignored. Please check the ordering in your security:http namespace or FilterChainProxy bean configuration
这是因为Spring Security的过滤器链是按定义顺序匹配请求的——先被定义的链会优先匹配请求,一旦匹配成功,后面的链就不会生效了。你现在把所有规则都塞进了一个pattern="/**"的通用过滤器链里,再加上自定义Servlet的路径匹配有小问题,才导致规则失效。
另外还要注意:你的自定义Servlet路径是/notification/event,但你配置的<security:intercept-url>是/notification/event/**——这个模式仅匹配该路径下的子资源,不会匹配/notification/event本身,这也是规则没生效的一个关键细节。
解决方案(无需转Java配置)
只需要在你的Security XML中调整<security:http>块的顺序,把针对自定义Servlet路径的规则单独放在一个前置的过滤器链中,就能让它优先被匹配,避免被通用规则覆盖。
步骤1:添加前置的专用过滤器链
在原有的通用<security:http>块之前,添加一个专门处理/notification/event的过滤器链:
<!-- 专门处理自定义Servlet的路径,放在最前面优先匹配 --> <security:http create-session="stateless" use-expressions="true" authentication-manager-ref="authenticationManager" entry-point-ref="http403EntryPoint" pattern="/notification/event"> <!-- 匹配自定义Servlet的精确路径 --> <security:intercept-url pattern="/notification/event" access="authenticated" /> <security:csrf disabled="true" /> <!-- 复用你原有自定义过滤器,保持和通用链一致的认证逻辑 --> <security:custom-filter ref="uniqueRequestFilter" before="FORM_LOGIN_FILTER" /> <security:custom-filter ref="encryptionFilter" after="FORM_LOGIN_FILTER"/> <security:custom-filter ref="hmacAuthenticationFilter" before="BASIC_AUTH_FILTER"/> </security:http>
步骤2:清理通用链中的重复规则
在原有的通用<security:http>块中,删除掉<security:intercept-url pattern="/notification/event/**" access="authenticated" />这条规则,因为已经有专用链处理该路径了。
为什么这样有效?
Spring Security会按<security:http>块的定义顺序依次匹配请求:
- 当请求
/notification/event进来时,会先匹配到前置的专用过滤器链,对应的认证规则和过滤器会生效; - 其他所有请求则会匹配后面的通用
/**过滤器链,完全不影响你原有的业务逻辑。
额外注意事项
确保你的ServletRegistrationBean中的路径和Security配置的pattern完全匹配:
@Bean public ServletRegistrationBean servletRegistrationBean() { // 路径是"/notification/event",Security中也要用相同的精确路径 ServletRegistrationBean bean = new ServletRegistrationBean(new EventDispatcherServlet(), "/notification/event"); return bean; }
如果你的Servlet需要处理该路径下的子资源(比如/notification/event/detail),再把Security的pattern改成/notification/event/**即可。
内容的提问来源于stack exchange,提问作者Viktor




