You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Spring Security中配置自定义RelayState及依赖方注册仓库问题

Spring Security SAML2动态设置RelayState及Repository Bean创建方案

一、动态设置RelayState传递redirectUrl

之前用SAML扩展库重写SAMLEntryPoint.getProfileOptions()的方式,在Spring Security SAML2里不适用。要实现运行时传递redirectUrl作为RelayState,得自定义Saml2AuthenticationRequestResolver替换默认实现:

  1. 编写自定义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);
    }
}
  1. 注册自定义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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.03 21:00:23