Spring Security中配置自定义RelayState及依赖方注册仓库问题
Spring Security SAML2动态设置RelayState及Repository Bean创建方案
一、动态设置RelayState传递redirectUrl
之前用SAML扩展库重写SAMLEntryPoint.getProfileOptions()的方式,在Spring Security SAML2里不适用。要实现运行时传递redirectUrl作为RelayState,得自定义Saml2AuthenticationRequestResolver替换默认实现:
- 编写自定义Resolver类,从当前请求中获取redirectUrl并注入到认证请求的RelayState中:
import org.springframework.security.saml2.provider.service.authentication.Saml2AuthenticationRequestContext; import org.springframework.security.saml2.provider.service.web.authentication.Saml2AuthenticationRequestResolver; import jakarta.servlet.http.HttpServletRequest; public class CustomSaml2AuthRequestResolver extends Saml2AuthenticationRequestResolver { public CustomSaml2AuthRequestResolver(RelyingPartyRegistrationRepository repository) { super(repository); } @Override protected void configureAuthenticationRequest(Saml2AuthenticationRequestContext context) { // 从请求参数、会话等位置获取运行时的redirectUrl,这里以请求参数为例 HttpServletRequest request = context.getRequest(); String redirectUrl = request.getParameter("redirectUrl"); if (redirectUrl != null) { context.getAuthenticationRequest().setRelayState(redirectUrl); } super.configureAuthenticationRequest(context); } }
- 注册自定义Resolver到Spring Security过滤器链:
Java配置(推荐,灵活性更高)
import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.security.config.annotation.web.builders.HttpSecurity; import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity; import org.springframework.security.web.SecurityFilterChain; @Configuration @EnableWebSecurity public class SecurityConfig { private final RelyingPartyRegistrationRepository repo; public SecurityConfig(RelyingPartyRegistrationRepository repo) { this.repo = repo; } @Bean public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception { http .authorizeHttpRequests(auth -> auth.anyRequest().authenticated()) .saml2Login(saml2 -> saml2 .authenticationRequestResolver(new CustomSaml2AuthRequestResolver(repo)) ); return http.build(); } }
XML配置(如果必须用XML)
先把自定义Resolver注册为Bean,再在saml2-login中引用:
<bean id="customAuthRequestResolver" class="com.yourpackage.CustomSaml2AuthRequestResolver"> <constructor-arg ref="relyingPartyRegistrationRepository"/> </bean> <http> <saml2-login authentication-request-resolver-ref="customAuthRequestResolver"/> </http>
二、创建支持别名引用的RelyingPartyRegistrationRepository Bean
用Spring Security提供的InMemoryRelyingPartyRegistrationRepository即可,它支持通过registrationId(别名)引用对应的RelyingPartyRegistration实例:
Java配置(推荐)
import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.security.saml2.provider.service.registration.InMemoryRelyingPartyRegistrationRepository; import org.springframework.security.saml2.provider.service.registration.RelyingPartyRegistration; import org.springframework.security.saml2.provider.service.registration.RelyingPartyRegistrations; @Configuration public class Saml2RegistrationConfig { @Bean public InMemoryRelyingPartyRegistrationRepository relyingPartyRegistrationRepository() { // 创建第一个IDP的注册,别名设为"idp1" RelyingPartyRegistration idp1 = RelyingPartyRegistrations .fromMetadataLocation("classpath:idp1-metadata.xml") .registrationId("idp1") .build(); // 创建第二个IDP的注册,别名设为"idp2" RelyingPartyRegistration idp2 = RelyingPartyRegistrations .fromMetadataLocation("classpath:idp2-metadata.xml") .registrationId("idp2") .build(); return new InMemoryRelyingPartyRegistrationRepository(idp1, idp2); } }
之后在其他地方要引用特定IDP的配置时,直接通过别名从Repository获取:
@Autowired private RelyingPartyRegistrationRepository repo; public void getSpecificIdpConfig() { repo.findByRegistrationId("idp1").ifPresent(registration -> { // 使用该注册配置做后续操作 }); }
XML配置
如果要用XML创建,先定义各个RelyingPartyRegistration Bean,再传入Repository的构造方法:
<!-- 定义第一个IDP的注册Bean --> <bean id="idp1Registration" class="org.springframework.security.saml2.provider.service.registration.RelyingPartyRegistration"> <!-- 这里可通过构造器或setter配置属性,比如metadata地址、registrationId等 --> <!-- 注意:XML配置RelyingPartyRegistration比较繁琐,推荐用Java配置的构建器API --> </bean> <!-- 定义第二个IDP的注册Bean --> <bean id="idp2Registration" class="org.springframework.security.saml2.provider.service.registration.RelyingPartyRegistration"> <!-- 配置对应属性 --> </bean> <!-- 创建Repository Bean --> <bean id="relyingPartyRegistrationRepository" class="org.springframework.security.saml2.provider.service.registration.InMemoryRelyingPartyRegistrationRepository"> <constructor-arg> <list> <ref bean="idp1Registration"/> <ref bean="idp2Registration"/> </list> </constructor-arg> </bean>
内容的提问来源于stack exchange,提问作者AbhishekB
相关产品推荐
相关产品推荐

