Spring Security SAML2 为它们动态选择 IDP 或动态 URL

ATr*_*bka 6 java spring spring-security saml-2.0 spring-security-saml2

我们正在尝试在应用程序中配置多个身份提供者以支持不同类型的 SSO。问题在于,对于未经身份验证的请求,应用程序不知道要重定向到哪个 IDP。我们可以根据域名确定使用哪个IDP。那不是问题。问题是更改过滤器重定向到该特定 IDP 的方式,而不是第一个找到的 IDP。

我想知道是否有一种简单的方法可以在 Spring Security 或其 SAML2 库中支持它。

我可以以某种方式修改元数据以将其重定向到我自己的 URL(然后在那里有一些自定义代码),或者让身份验证过滤器根据某些标准选择正确的 IDP。

更新

当前 yaml 配置:

spring:
  security:
    saml2:
      relyingparty:
        registration:
          idpone:
            identityprovider:
              entity-id: https://idpone.com
              sso-url: https://idpone.com
              verification: 
                credentials:
                - certificate-location: "classpath:saml/idpone.crt"
          idptwo:
            identityprovider:
              entity-id: https://idptwo.com
              sso-url: https://idptwo.com
              verification: 
                credentials:
                - certificate-location: "classpath:saml/idptwo.crt"
Run Code Online (Sandbox Code Playgroud)

jzh*_*aux 5

从 Spring Security 5.2 开始,您可以通过RelyingPartyRegistrationRepository.

使用 Spring Boot 时,每个看起来像这样:

spring:
  security:
    saml2:
      relyingparty:
        registration:
          idpone:
            identityprovider:
              verification:
                credentials:
                  - certificate-location: "classpath:idpOne.crt"
              entity-id: https://idp.example.org
              sso-url: https://idp.example.org/SSOService.saml2
          idptwo:
            identityprovider:
              ...
Run Code Online (Sandbox Code Playgroud)

然后,您可以idpOne通过导航到启动AuthNRequest http://localhost:8080/saml2/authenticate/idpOne

按主机名

如果您想通过主机名执行此操作,则可以自定义/login页面以了解/saml2/authenticate/{registrationId}要重定向到哪个端点。

首先,你会告诉 Spring Security 你有一个自定义/login页面,所以它不会创建一个:

@Configuration
public class SecurityConfig extends WebSecurityConfigurerAdapter {

    @Override
    protected void configure(HttpSecurity http) {
        http
            .authorizeRequests(authz -> authz
                .mvcMatchers("/login").permitAll() // here
                .anyRequest().authenticated())
            .saml2Login(saml2 -> saml2.loginPage("/login")) // and here
    }

}
Run Code Online (Sandbox Code Playgroud)

然后,你定义它:

@Configuration
public class SecurityConfig extends WebSecurityConfigurerAdapter {

    @Override
    protected void configure(HttpSecurity http) {
        http
            .authorizeRequests(authz -> authz
                .mvcMatchers("/login").permitAll() // here
                .anyRequest().authenticated())
            .saml2Login(saml2 -> saml2.loginPage("/login")) // and here
    }

}
Run Code Online (Sandbox Code Playgroud)

/login端点中查找的原因是为了确保registrationId主机名中提供的内容是合法的。