Spring Security SAML2升级1.0.0至1.0.3遇URL重写致端点未找到问题
我之前维护类似架构的项目时,也碰到过Spring Security SAML2从1.0.0升级到1.0.3后,因Apache URL重写+Tomcat上下文路径导致的校验失败问题。新版本对ACS(Assertion Consumer Service)URL的校验逻辑更严格,自动推导的URL和IdP配置的不一致就会触发错误。下面是几个经过验证的解决方案:
1. 启用Forwarded Header处理,让Spring获取真实请求URL
Apache反向代理时会添加X-Forwarded-*系列请求头,告知后端真实的请求地址。你需要让Spring Security正确识别这些头,生成和IdP匹配的ACS URL:
方式一:配置ForwardedHeaderFilter(适用于Spring Security 5+)
在你的SecurityFilterChain配置中,将这个过滤器放在最前面,确保它优先处理请求:
@Bean public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception { http // 先添加ForwardedHeaderFilter处理代理头 .addFilterBefore(new ForwardedHeaderFilter(), UsernamePasswordAuthenticationFilter.class) .saml2Login(saml2 -> saml2 // 你的SAML2登录配置 ); return http.build(); }
方式二:Spring Boot自动配置
如果是Spring Boot应用,直接在application.properties/application.yml中开启转发头策略:
server.forward-headers-strategy=native
这个配置会让Spring Boot自动注册ForwardedHeaderFilter,并正确解析Apache传递的头信息。
2. 显式指定ACS URL,跳过自动推导
如果不想依赖头信息处理,可以直接在SAML2依赖方注册中硬编码IdP那边配置的ACS URL:
Java配置方式
@Bean public RelyingPartyRegistrationRepository relyingPartyRegistrationRepository() { RelyingPartyRegistration registration = RelyingPartyRegistration.withRegistrationId("your-reg-id") .assertionConsumerServiceLocation("https://your-public-domain/saml/SSO") // 其他配置(IdP元数据、证书等) .build(); return new InMemoryRelyingPartyRegistrationRepository(registration); }
配置文件方式
spring.security.saml2.relyingparty.registration.your-reg-id.assertion-consumer-service.location=https://your-public-domain/saml/SSO
这种方式最直接,确保框架使用的ACS URL和IdP后台配置的完全一致,避免自动推导带来的偏差。
3. 修正Apache的反向代理配置
确保Apache在转发请求时传递了正确的头信息,让后端能还原真实URL。修改你的Apache虚拟主机配置:
<VirtualHost *:443> ServerName your-public-domain.com # 反向代理到Tomcat ProxyPass /ctx/ http://localhost:8080/ctx/ ProxyPassReverse /ctx/ http://localhost:8080/ctx/ # 保留原始主机头 ProxyPreserveHost On # 传递真实的协议、端口和路径 RequestHeader set X-Forwarded-Proto "https" RequestHeader set X-Forwarded-Port "443" RequestHeader set X-Forwarded-Path "/ctx" # SSL配置(省略) </VirtualHost>
ProxyPreserveHost On很关键,它会让Tomcat拿到前端的真实域名,而不是localhost。
为什么升级后出现问题?
Spring Security SAML2 1.0.3版本收紧了ACS URL的校验逻辑,1.0.0版本可能对URL的匹配更宽松,允许上下文路径的差异,但新版本会严格校验回调URL是否和IdP发送的断言中的地址完全一致,所以之前隐藏的URL不一致问题就暴露出来了。
内容的提问来源于stack exchange,提问作者Hapeka

