此版本仍在开发中,尚未被视为稳定版本。对于最新的稳定版本,请使用 Spring Security 6.4.1spring-doc.cadn.net.cn

生产<saml2:AuthnRequest>s

如前所述,Spring Security 的 SAML 2.0 支持产生了一个<saml2:AuthnRequest>开始对断言方进行身份验证。spring-doc.cadn.net.cn

Spring Security 在一定程度上是通过注册Saml2WebSsoAuthenticationRequestFilter在过滤器链中。 默认情况下,此筛选条件会响应 endpoint/saml2/authenticate/{registrationId}.spring-doc.cadn.net.cn

例如,如果您被部署到rp.example.com,并且您为注册指定的 ID 为okta,您可以导航到:spring-doc.cadn.net.cn

结果将是一个包含SAMLRequest参数,其中包含 signed、deflated 和 encoded<saml2:AuthnRequest>.spring-doc.cadn.net.cn

更改<saml2:AuthnRequest>获取存储

Saml2WebSsoAuthenticationRequestFilter使用Saml2AuthenticationRequestRepository要持久保存AbstractSaml2AuthenticationRequest实例前发送<saml2:AuthnRequest>对主张方。spring-doc.cadn.net.cn

此外Saml2WebSsoAuthenticationFilterSaml2AuthenticationTokenConverter使用Saml2AuthenticationRequestRepository加载任何AbstractSaml2AuthenticationRequest作为验证<saml2:Response>.spring-doc.cadn.net.cn

默认情况下,Spring Security 使用HttpSessionSaml2AuthenticationRequestRepository,它将AbstractSaml2AuthenticationRequestHttpSession.spring-doc.cadn.net.cn

如果您有Saml2AuthenticationRequestRepository,您可以通过将其公开为@Bean如以下示例所示:spring-doc.cadn.net.cn

@Bean
Saml2AuthenticationRequestRepository<AbstractSaml2AuthenticationRequest> authenticationRequestRepository() {
	return new CustomSaml2AuthenticationRequestRepository();
}
@Bean
open fun authenticationRequestRepository(): Saml2AuthenticationRequestRepository<AbstractSaml2AuthenticationRequest> {
    return CustomSaml2AuthenticationRequestRepository()
}

更改<saml2:AuthnRequest>被发送

默认情况下,Spring Security 会对每个<saml2:AuthnRequest>并将其作为 GET 发送给断言方。spring-doc.cadn.net.cn

许多主张方不需要签名<saml2:AuthnRequest>. 这可以通过RelyingPartyRegistrations,或者您可以手动提供它,如下所示:spring-doc.cadn.net.cn

不需要签名的 AuthnRequest
spring:
  security:
    saml2:
      relyingparty:
        okta:
          identityprovider:
            entity-id: ...
            singlesignon.sign-request: false
RelyingPartyRegistration relyingPartyRegistration = RelyingPartyRegistration.withRegistrationId("okta")
        // ...
        .assertingPartyDetails(party -> party
            // ...
            .wantAuthnRequestsSigned(false)
        )
        .build();
var relyingPartyRegistration: RelyingPartyRegistration =
    RelyingPartyRegistration.withRegistrationId("okta")
        // ...
        .assertingPartyDetails { party: AssertingPartyDetails.Builder -> party
                // ...
                .wantAuthnRequestsSigned(false)
        }
        .build()

否则,您需要指定一个私有密钥来RelyingPartyRegistration#signingX509Credentials以便 Spring Security 可以签署<saml2:AuthnRequest>在发送之前。spring-doc.cadn.net.cn

默认情况下,Spring Security 将对<saml2:AuthnRequest>rsa-sha256,但某些断言方将需要不同的算法,如其元数据中所示。spring-doc.cadn.net.cn

或者,您可以手动提供:spring-doc.cadn.net.cn

String metadataLocation = "classpath:asserting-party-metadata.xml";
RelyingPartyRegistration relyingPartyRegistration = RelyingPartyRegistrations.fromMetadataLocation(metadataLocation)
        // ...
        .assertingPartyDetails((party) -> party
            // ...
            .signingAlgorithms((sign) -> sign.add(SignatureConstants.ALGO_ID_SIGNATURE_RSA_SHA512))
        )
        .build();
var metadataLocation = "classpath:asserting-party-metadata.xml"
var relyingPartyRegistration: RelyingPartyRegistration =
    RelyingPartyRegistrations.fromMetadataLocation(metadataLocation)
        // ...
        .assertingPartyDetails { party: AssertingPartyDetails.Builder -> party
                // ...
                .signingAlgorithms { sign: MutableList<String?> ->
                    sign.add(
                        SignatureConstants.ALGO_ID_SIGNATURE_RSA_SHA512
                    )
                }
        }
        .build()
上面的代码段使用 OpenSAMLSignatureConstantsclass 来提供算法名称。 但是,这只是为了方便。 由于数据类型为String中,您可以直接提供算法的名称。

一些主张方要求<saml2:AuthnRequest>被发布。 这可以通过RelyingPartyRegistrations,或者您可以手动提供它,如下所示:spring-doc.cadn.net.cn

RelyingPartyRegistration relyingPartyRegistration = RelyingPartyRegistration.withRegistrationId("okta")
        // ...
        .assertingPartyDetails(party -> party
            // ...
            .singleSignOnServiceBinding(Saml2MessageBinding.POST)
        )
        .build();
var relyingPartyRegistration: RelyingPartyRegistration? =
    RelyingPartyRegistration.withRegistrationId("okta")
        // ...
        .assertingPartyDetails { party: AssertingPartyDetails.Builder -> party
            // ...
            .singleSignOnServiceBinding(Saml2MessageBinding.POST)
        }
        .build()

自定义 OpenSAML 的AuthnRequest实例

出于多种原因,您可能希望调整AuthnRequest. 例如,您可能希望ForceAuthN设置为true,Spring Security 设置为false默认情况下。spring-doc.cadn.net.cn

您可以自定义 OpenSAML 的AuthnRequest通过发布OpenSaml4AuthenticationRequestResolver作为@Bean这样:spring-doc.cadn.net.cn

@Bean
Saml2AuthenticationRequestResolver authenticationRequestResolver(RelyingPartyRegistrationRepository registrations) {
    RelyingPartyRegistrationResolver registrationResolver =
            new DefaultRelyingPartyRegistrationResolver(registrations);
    OpenSaml4AuthenticationRequestResolver authenticationRequestResolver =
            new OpenSaml4AuthenticationRequestResolver(registrationResolver);
    authenticationRequestResolver.setAuthnRequestCustomizer((context) -> context
            .getAuthnRequest().setForceAuthn(true));
    return authenticationRequestResolver;
}
@Bean
fun authenticationRequestResolver(registrations : RelyingPartyRegistrationRepository) : Saml2AuthenticationRequestResolver {
    val registrationResolver : RelyingPartyRegistrationResolver =
            new DefaultRelyingPartyRegistrationResolver(registrations)
    val authenticationRequestResolver : OpenSaml4AuthenticationRequestResolver =
            new OpenSaml4AuthenticationRequestResolver(registrationResolver)
    authenticationRequestResolver.setAuthnRequestCustomizer((context) -> context
            .getAuthnRequest().setForceAuthn(true))
    return authenticationRequestResolver
}