生成 <saml2:AuthnRequest>

本站(springdoc.cn)中的内容来源于 spring.io ,原始版权归属于 spring.io。由 springdoc.cn 进行翻译,整理。可供个人学习、研究,未经许可,不得进行任何转载、商用或与之相关的行为。 商标声明:Spring 是 Pivotal Software, Inc. 在美国以及其他国家的商标。

如前所述,Spring Security 的 SAML 2.0 支持产生一个 <saml2:AuthnRequest> 来开始与断言方进行认证。

Spring Security通过在过滤器链中注册 Saml2WebSsoAuthenticationRequestFilter 部分实现了这一点。这个过滤器默认响应端点 /saml2/authenticate/{registrationId}

例如,如果你被部署到 rp.example.com,并且你给你的注册的ID是 okta,你可以导航到:

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

改变 <saml2:AuthnRequest> 的存储方式

Saml2WebSsoAuthenticationRequestFilter 在向断言方 发送 <saml2:AuthnRequest> 之前,使用 Saml2AuthenticationRequestRepository 来持久化一个 AbstractSaml2AuthenticationRequest 实例。

此外,Saml2WebSsoAuthenticationFilterSaml2AuthenticationTokenConverter 使用 Saml2AuthenticationRequestRepository 来加载任何 AbstractSaml2AuthenticationRequest 作为 验证 <saml2:Response>的一部分。

默认情况下,Spring Security 使用一个 HttpSessionSaml2AuthenticationRequestRepository,它将 AbstractSaml2AuthenticationRequest 存储在 HttpSession 中。

如果你有一个 Saml2AuthenticationRequestRepository 的自定义实现,你可以通过将其暴露为一个 @Bean 来配置它,如下例所示。

  • Java

  • Kotlin

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

改变 <saml2:AuthnRequest> 的发送方式

默认情况下,Spring Security 对每个 <saml2:AuthnRequest> 进行签名,并将其作为 GET 发送到断言方。

许多断言方不需要签名的 <saml2:AuthnRequest>。这可以通过 RelyingPartyRegistrations 自动配置,或者你可以手动提供,像这样。

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>

默认情况下,Spring Security 将使用 rsa-sha256<saml2:AuthnRequest> 进行签名,尽管一些断言方需要不同的算法,正如他们的元数据中指出的那样。

或者,你可以手动提供它。

  • 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,你可以直接提供算法的名称。

一些断言方要求 <saml2:AuthnRequest> 被POST。这可以通过 RelyingPartyRegistrations 自动配置,或者你可以手动提供,像这样。

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

自定义 OpenSAML 的 AuthnRequest 实例

你可能想调整一个 AuthnRequest,有很多原因。例如,你可能希望 ForceAuthN 被设置为 true,而 Spring Security 默认将其设置为 false

你可以通过发布一个 OpenSaml4AuthenticationRequestResolver 作为 @Bean 来定制 OpenSAML 的 AuthnRequest 的元素,就像这样。

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