Producing `<saml2:AuthnRequest>`s

如前所述,Spring Security 的 SAML 2.0 支持会产生 <saml2:AuthnRequest> 以开始与声明方的验证。

As stated earlier, Spring Security’s SAML 2.0 support produces a <saml2:AuthnRequest> to commence authentication with the asserting party.

Spring Security 部分通过在过滤器链中注册 Saml2WebSsoAuthenticationRequestFilter 来实现这一点。该过滤器默认对 /saml2/authenticate/{registrationId} 终端节点做出响应。

Spring Security achieves this in part by registering the Saml2WebSsoAuthenticationRequestFilter in the filter chain. This filter by default responds to endpoint /saml2/authenticate/{registrationId}.

例如,如果您已部署到 https://rp.example.com 并且您的注册 ID 为 okta,您可以导航到:

For example, if you were deployed to https://rp.example.com and you gave your registration an ID of okta, you could navigate to: https://rp.example.org/saml2/authenticate/okta

结果将是重定向,其中包含一个 SAMLRequest 参数,该参数包含已签名、已压缩和已编码的 <saml2:AuthnRequest>

and the result would be a redirect that included a SAMLRequest parameter containing the signed, deflated, and encoded <saml2:AuthnRequest>.

Changing How the <saml2:AuthnRequest> Gets Stored

Saml2WebSsoAuthenticationRequestFilter 使用 Saml2AuthenticationRequestRepositorysending the <saml2:AuthnRequest> 之前将 AbstractSaml2AuthenticationRequest 实例持久化到声明方。

Saml2WebSsoAuthenticationRequestFilter uses an Saml2AuthenticationRequestRepository to persist an AbstractSaml2AuthenticationRequest instance before sending the <saml2:AuthnRequest> to the asserting party.

此外,Saml2WebSsoAuthenticationFilterSaml2AuthenticationTokenConverter 使用 Saml2AuthenticationRequestRepository 加载所有 AbstractSaml2AuthenticationRequest 作为 authenticating the <saml2:Response> 的一部分。

Additionally, Saml2WebSsoAuthenticationFilter and Saml2AuthenticationTokenConverter use an Saml2AuthenticationRequestRepository to load any AbstractSaml2AuthenticationRequest as part of authenticating the <saml2:Response>.

默认情况下,Spring Security 使用 HttpSessionSaml2AuthenticationRequestRepository,它存储在 HttpSession 中的 AbstractSaml2AuthenticationRequest

By default, Spring Security uses an HttpSessionSaml2AuthenticationRequestRepository, which stores the AbstractSaml2AuthenticationRequest in the HttpSession.

如果您有 Saml2AuthenticationRequestRepository 的自定义实现,您可以通过将其公开为 @Bean 来配置它,如下例所示:

If you have a custom implementation of Saml2AuthenticationRequestRepository, you may configure it by exposing it as a @Bean as shown in the following example:

  • Java

  • Kotlin

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

Changing How the <saml2:AuthnRequest> Gets Sent

默认情况下,Spring Security 签署每个 <saml2:AuthnRequest> 并作为 GET 发送到声明方。

By default, Spring Security signs each <saml2:AuthnRequest> and send it as a GET to the asserting party.

许多声明方不需要签名的 <saml2:AuthnRequest>。这可以通过 RelyingPartyRegistrations 自动配置,或者您可以手动提供,如下所示:

Many asserting parties don’t require a signed <saml2:AuthnRequest>. This can be configured automatically via RelyingPartyRegistrations, or you can supply it manually, like so:

Not Requiring Signed AuthnRequests
  • Boot

  • Java

  • Kotlin

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>

Otherwise, you will need to specify a private key to RelyingPartyRegistration#signingX509Credentials so that Spring Security can sign the <saml2:AuthnRequest> before sending.

默认情况下,Spring Security 将使用 rsa-sha256 签名 <saml2:AuthnRequest>,尽管某些声明方需要不同的算法,如其元数据中所示。

By default, Spring Security will sign the <saml2:AuthnRequest> using rsa-sha256, though some asserting parties will require a different algorithm, as indicated in their metadata.

您可以基于声明方的 metadata using RelyingPartyRegistrations 配置算法。

You can configure the algorithm based on the asserting party’s metadata using RelyingPartyRegistrations.

或者,可以手动提供它:

Or, you can provide it manually:

  • Java

  • Kotlin

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();

上面的代码片段使用 OpenSAML SignatureConstants 类来提供算法名称。但这只是为了方便。由于数据类型为 String,您可以直接提供算法名称。

The snippet above uses the OpenSAML SignatureConstants class to supply the algorithm name. But, that’s just for convenience. Since the datatype is String, you can supply the name of the algorithm directly.

某些声明方要求提交 <saml2:AuthnRequest>。这可以通过 RelyingPartyRegistrations 自动配置,也可以手动提供它,如下所示:

Some asserting parties require that the <saml2:AuthnRequest> be POSTed. This can be configured automatically via RelyingPartyRegistrations, or you can supply it manually, like so:

  • Java

  • Kotlin

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()

Customizing OpenSAML’s AuthnRequest Instance

有很多理由需要调整 AuthnRequest。例如,您可能希望 ForceAuthN 设置为 true,Spring Security 默认将其设置为 false

There are a number of reasons that you may want to adjust an AuthnRequest. For example, you may want ForceAuthN to be set to true, which Spring Security sets to false by default.

可以通过发布一个 OpenSaml4AuthenticationRequestResolver 作为 @Bean 来自定义 OpenSAML 的 AuthnRequest 元素,如下所示:

You can customize elements of OpenSAML’s AuthnRequest by publishing an OpenSaml4AuthenticationRequestResolver as a @Bean, like so:

  • Java

  • Kotlin

@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
}