7

我们正在尝试在应用程序中配置多个身份提供程序以支持不同类型的 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"
4

1 回答 1

6

从 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:
              ...

然后,您可以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
    }

}

然后,你会定义它:

@Controller
public class LoginController {
    private final RelyingPartyRegistrationRepository relyingParties;

    // ... constructor

    @GetMapping("/login")
    public void login(HttpServletRequest request, HttpServletResponse response) {
        String registrationId = // ... derive from the host name
        RelyingPartyRegistration relyingParty = this.relyingParties
                .findByRegistrationId(registrationId);
        if (relyingParty == null) {
            response.setStatusCode(401);
        } else {
            response.sendRedirect("/saml2/authenticate/" + registrationId);
        }
    }
}

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

于 2020-03-10T22:14:55.083 回答