Saml 2.0 元資料

Spring Security 可以解析斷言方元資料以生成一個 AssertingPartyMetadata 例項,並可以從 RelyingPartyRegistration 例項釋出依賴方元資料

解析 <saml2:IDPSSODescriptor> 元資料

您可以使用 RelyingPartyRegistrations 解析斷言方的元資料。

當使用 OpenSAML 供應商支援時,生成的 AssertingPartyMetadata 將是 OpenSamlAssertingPartyDetails 型別。這意味著您可以透過以下方式獲取底層的 OpenSAML XMLObject

  • Java

  • Kotlin

OpenSamlAssertingPartyDetails details = (OpenSamlAssertingPartyDetails)
        registration.getAssertingPartyMetadata();
EntityDescriptor openSamlEntityDescriptor = details.getEntityDescriptor();
val details: OpenSamlAssertingPartyDetails =
        registration.getAssertingPartyMetadata() as OpenSamlAssertingPartyDetails
val openSamlEntityDescriptor: EntityDescriptor = details.getEntityDescriptor()

使用 AssertingPartyMetadataRepository

您也可以透過使用 AssertingPartyMetadataRepository 來比 RelyingPartyRegistrations 更具針對性,它是一個只允許檢索斷言方元資料的介面。

這提供了三個有價值的特性

  • 實現可以在感知到過期時重新整理斷言方元資料

  • RelyingPartyRegistrationRepository 的實現可以更容易地闡明依賴方與其一個或多個相應斷言方之間的關係

  • 實現可以驗證元資料簽名

例如,OpenSaml4AssertingPartyMetadataRepository 使用 OpenSAML 的 MetadataResolver,這是一個 API,其實現會定期地在感知到過期時重新整理底層元資料。

這意味著您現在只需幾行程式碼就可以建立一個可重新整理的 RelyingPartyRegistrationRepository

  • Java

  • Kotlin

@Component
public class RefreshableRelyingPartyRegistrationRepository
        implements IterableRelyingPartyRegistrationRepository {

	private final AssertingPartyMetadataRepository metadata =
            OpenSamlAssertingPartyMetadataRepository
                .fromTrustedMetadataLocation("https://idp.example.org/metadata").build();

	@Override
    public RelyingPartyRegistration findByRegistrationId(String registrationId) {
		AssertingPartyMetadata metadata = this.metadata.findByEntityId(registrationId);
        if (metadata == null) {
            return null;
        }
		return applyRelyingParty(metadata);
    }

	@Override
    public Iterator<RelyingPartyRegistration> iterator() {
		return StreamSupport.stream(this.metadata.spliterator(), false)
            .map(this::applyRelyingParty).iterator();
    }

	private RelyingPartyRegistration applyRelyingParty(AssertingPartyMetadata metadata) {
		return RelyingPartyRegistration.withAssertingPartyMetadata(metadata)
            // apply any relying party configuration
            .build();
	}

}
@Component
class RefreshableRelyingPartyRegistrationRepository : IterableRelyingPartyRegistrationRepository {

    private val metadata: AssertingPartyMetadataRepository =
        OpenSamlAssertingPartyMetadataRepository.fromTrustedMetadataLocation(
            "https://idp.example.org/metadata").build()

    fun findByRegistrationId(registrationId:String?): RelyingPartyRegistration {
        val metadata = this.metadata.findByEntityId(registrationId)
        if (metadata == null) {
            return null
        }
        return applyRelyingParty(metadata)
    }

    fun iterator(): Iterator<RelyingPartyRegistration> {
        return StreamSupport.stream(this.metadata.spliterator(), false)
            .map(this::applyRelyingParty).iterator()
    }

    private fun applyRelyingParty(metadata: AssertingPartyMetadata): RelyingPartyRegistration {
        val details: AssertingPartyMetadata = metadata as AssertingPartyMetadata
        return RelyingPartyRegistration.withAssertingPartyMetadata(details)
            // apply any relying party configuration
            .build()
    }
 }
OpenSaml4AssertingPartyMetadataRepository 還提供了一個建構函式,以便您可以提供自定義的 MetadataResolver。由於底層的 MetadataResolver 負責過期和重新整理,如果您直接使用此建構函式,則只有在提供的實現具備這些功能時,您才能獲得這些特性。

驗證元資料簽名

您還可以透過提供適當的 Saml2X509Credential 集合來使用 OpenSaml4AssertingPartyMetadataRepository 驗證元資料簽名,如下所示

  • Java

  • Kotlin

OpenSamlAssertingPartyMetadataRepository.withMetadataLocation("https://idp.example.org/metadata")
    .verificationCredentials((c) -> c.add(myVerificationCredential))
    .build();
OpenSamlAssertingPartyMetadataRepository.withMetadataLocation("https://idp.example.org/metadata")
    .verificationCredentials({ c : Collection<Saml2X509Credential> ->
        c.add(myVerificationCredential) })
    .build()
如果未提供憑據,該元件將不會執行簽名驗證。

生成 <saml2:SPSSODescriptor> 元資料

您可以使用 saml2Metadata DSL 方法釋出一個元資料端點,如下所示

  • Java

  • Kotlin

http
    // ...
    .saml2Login(withDefaults())
    .saml2Metadata(withDefaults());
http {
    //...
    saml2Login { }
    saml2Metadata { }
}

您可以使用此元資料端點將您的依賴方註冊到您的斷言方。這通常很簡單,只需找到正確的表單欄位來提供元資料端點即可。

預設情況下,元資料端點是 `/saml2/metadata`,但它也響應 `/saml2/metadata/{registrationId}` 和 `/saml2/service-provider-metadata/{registrationId}`。

您可以透過在 DSL 中呼叫 metadataUrl 方法來更改此設定

  • Java

  • Kotlin

.saml2Metadata((saml2) -> saml2.metadataUrl("/saml/metadata"))
saml2Metadata {
	metadataUrl = "/saml/metadata"
}

更改查詢 RelyingPartyRegistration 的方式

如果您有不同的策略來確定使用哪個 RelyingPartyRegistration,您可以配置自己的 Saml2MetadataResponseResolver,如下所示

  • Java

  • Kotlin

@Bean
Saml2MetadataResponseResolver metadataResponseResolver(RelyingPartyRegistrationRepository registrations) {
	RequestMatcherMetadataResponseResolver metadata = new RequestMatcherMetadataResponseResolver(
			(id) -> registrations.findByRegistrationId("relying-party"));
	metadata.setMetadataFilename("metadata.xml");
	return metadata;
}
@Bean
fun metadataResponseResolver(val registrations: RelyingPartyRegistrationRepository): Saml2MetadataResponseResolver {
    val metadata = new RequestMatcherMetadataResponseResolver(
			id: String -> registrations.findByRegistrationId("relying-party"))
	metadata.setMetadataFilename("metadata.xml")
	return metadata
}