Spring Security 5.7.3:如何从子域名获取RegistrationId
从子域名获取Spring Security SAML2的registrationId解决方案
针对Spring Security 5.7.3版本,要实现从子域名提取registrationId,核心是替换默认的RelyingPartyRegistrationResolver,自定义逻辑从请求的主机地址中解析出子域名作为registrationId,具体步骤如下:
1. 自定义RelyingPartyRegistrationResolver实现类
创建自定义解析器,从请求的serverName中提取子域名,再根据该ID获取对应的SAML2依赖方注册信息:
import org.springframework.security.saml2.provider.service.registration.RelyingPartyRegistration; import org.springframework.security.saml2.provider.service.registration.RelyingPartyRegistrationRepository; import org.springframework.security.saml2.provider.service.web.RelyingPartyRegistrationResolver; import javax.servlet.http.HttpServletRequest; public class SubdomainRelyingPartyRegistrationResolver implements RelyingPartyRegistrationResolver { private final RelyingPartyRegistrationRepository repository; // 配置你的根域名,比如company.com private final String rootDomain = "company.com"; public SubdomainRelyingPartyRegistrationResolver(RelyingPartyRegistrationRepository repository) { this.repository = repository; } @Override public RelyingPartyRegistration resolve(HttpServletRequest request) { String serverName = request.getServerName(); // 提取子域名作为registrationId String registrationId = extractSubdomain(serverName); if (registrationId == null) { return null; } return repository.findByRegistrationId(registrationId); } @Override public RelyingPartyRegistration resolve(HttpServletRequest request, String registrationId) { // 保留原有按ID查找的逻辑,兼容其他场景 return repository.findByRegistrationId(registrationId); } private String extractSubdomain(String serverName) { if (!serverName.endsWith("." + rootDomain)) { return null; } // 拆分出子域名部分,比如someregid.company.com -> someregid return serverName.substring(0, serverName.length() - (rootDomain.length() + 1)); } }
2. 集成自定义解析器到Security配置
在SecurityFilterChain配置中,替换默认解析器,同时调整loginProcessingUrl为固定路径(不再需要从路径获取registrationId):
import org.springframework.security.config.annotation.web.builders.HttpSecurity; import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity; import org.springframework.security.saml2.provider.service.registration.RelyingPartyRegistrationRepository; import org.springframework.security.web.SecurityFilterChain; @EnableWebSecurity public class SecurityConfig { private final RelyingPartyRegistrationRepository relyingPartyRegistrationRepository; public SecurityConfig(RelyingPartyRegistrationRepository relyingPartyRegistrationRepository) { this.relyingPartyRegistrationRepository = relyingPartyRegistrationRepository; } public SecurityFilterChain filterChain(HttpSecurity http) throws Exception { // 自定义解析器实例 SubdomainRelyingPartyRegistrationResolver customResolver = new SubdomainRelyingPartyRegistrationResolver(relyingPartyRegistrationRepository); http .authorizeRequests() .antMatchers("/authorized").hasRole("USER") .anyRequest().authenticated() .and() .saml2Login() .successHandler(new MySamlLoginSuccessHandler()) .loginProcessingUrl("/saml/SSO") // 固定路径,不再需要{registrationId} .relyingPartyRegistrationResolver(customResolver); // 设置自定义解析器 return http.build(); } }
关键说明
- 自定义解析器通过
request.getServerName()获取完整域名,拆分出子域名作为registrationId,再从RelyingPartyRegistrationRepository中查找对应的注册配置。 - 调整
loginProcessingUrl为固定的/saml/SSO,因为现在不再依赖路径变量传递registrationId。 - 子域名提取逻辑可以根据实际域名结构调整,比如处理多级子域名、根域名带端口的场景等。
内容的提问来源于stack exchange,提问作者jkerr
相关产品推荐
相关产品推荐

