Spring 6.0+Spring Security 6.1中REST配置未拦截/rest/**端点问题
问题1:/rest/** 请求未被REST安全配置拦截
在Spring Security 6.x中,多个<security:http>对应的FilterChain是按配置顺序进行请求匹配的:
- 你的普通安全配置未指定
pattern,默认会匹配所有请求 - 如果普通配置定义在REST配置之前,所有请求(包括
/rest/**)会被第一个匹配的普通FilterChain处理,导致REST配置无法生效
修复方案
方案1:调整配置顺序
将REST的<security:http>配置放在普通配置之前。Spring Security会先检查请求是否匹配/rest/**,匹配成功则用REST的FilterChain处理,不匹配才会走到普通配置。
调整后的XML结构示例:
<!-- 先定义REST安全配置 --> <security:http security-context-explicit-save="true" use-expressions="true" use-authorization-manager="false" pattern="/rest/**" create-session="stateless" entry-point-ref="restServicesEntryPoint"> <security:custom-filter ref="restServicesFilter" position="BASIC_AUTH_FILTER" /> </security:http> <bean id="restServicesEntryPoint" class="com.example.webservices.auth.RestAuthenticationEntryPoint"> <property name="realmName" value="Square" /> </bean> <bean id="restServicesFilter" class="com.example.webservices.auth.CustomRestSecurityFilter"/> <!-- 后定义普通安全配置 --> <security:http create-session="stateless" security-context-explicit-save="true" use-authorization-manager="false" authentication-manager-ref="authenticationManagerWithMultipleProviders" security-context-repository-ref="nullSecurityContextRepository"> <!-- Login config --> <security:access-denied-handler error-page="/bs/denied"/> <!-- Login config --> <security:form-login login-page="/bs/login" authentication-success-handler-ref="customAuthenticationSuccessHandler" authentication-failure-handler-ref="customAuthenticationFailureHandler" /> //other codes </security:http>
方案2:给普通配置添加请求排除规则
在普通配置中添加request-matcher,明确排除/rest/**路径,这样不管配置顺序如何,普通配置都不会处理REST请求:
<security:http create-session="stateless" security-context-explicit-save="true" use-authorization-manager="false" authentication-manager-ref="authenticationManagerWithMultipleProviders" security-context-repository-ref="nullSecurityContextRepository"> <!-- 排除/rest/**路径 --> <security:request-matcher path="/rest/**" negate="true"/> <!-- Login config --> <security:access-denied-handler error-page="/bs/denied"/> <!-- Login config --> <security:form-login login-page="/bs/login" authentication-success-handler-ref="customAuthenticationSuccessHandler" authentication-failure-handler-ref="customAuthenticationFailureHandler" /> //other codes </security:http>
问题2:移除use-authorization-manager=false出现循环依赖
Spring Security 6.x默认启用AuthorizationManager,若自定义了AuthenticationManager(如你的authenticationManagerWithMultipleProviders),容易出现循环依赖——因为AuthorizationManager会依赖AuthenticationManager,部分场景下AuthenticationManager又会反向依赖AuthorizationManager。
修复方案
避免直接在XML中硬编码
authentication-manager-ref:
改用Spring Security自动配置的AuthenticationManager,或者通过@Bean在配置类中暴露AuthenticationManager,而非XML直接引用。拆分配置依赖:
将AuthenticationManager的配置与FilterChain配置解耦,单独定义AuthenticationManager的Bean,确保它不依赖AuthorizationManager相关组件。保留
use-authorization-manager=false(临时兼容方案):
如果暂时无法调整依赖结构,可以继续保留该属性,先解决请求匹配问题,后续再逐步迁移到Spring Security 6.x的新授权模型。
内容的提问来源于stack exchange,提问作者Stackunderflow

