我是SAML的新手,并将其集成到Spring Web应用程序中。我首先按照此处的Spring SAML快速入门指南开始: http://docs.spring.io/spring-security-saml/docs/1.0.0.RELEASE/reference/html/chapter-quick-start.html
我的运行正常。然后我想切换到目标IDP,它已经在运行并成功服务于公司内的其他SP。
在我的securityContext.xml中,我将以下内容添加到元数据bean:
<bean class="org.springframework.security.saml.metadata.ExtendedMetadataDelegate">
<constructor-arg>
<bean class="org.opensaml.saml2.metadata.provider.FilesystemMetadataProvider">
<constructor-arg>
<value type="java.io.File">classpath:security/MyEntityId_sp.xml</value>
</constructor-arg>
<property name="parserPool" ref="parserPool"/>
</bean>
</constructor-arg>
<constructor-arg>
<bean class="org.springframework.security.saml.metadata.ExtendedMetadata">
<property name="local" value="true"/>
<property name="alias" value="myAlias"/>
<property name="securityProfile" value="metaiop"/>
<property name="sslSecurityProfile" value="pkix"/>
<property name="signingKey" value="apollo"/>
<property name="encryptionKey" value="apollo"/>
<property name="requireArtifactResolveSigned" value="false"/>
<property name="requireLogoutRequestSigned" value="false"/>
<property name="requireLogoutResponseSigned" value="false"/>
<property name="idpDiscoveryEnabled" value="false"/>
</bean>
</constructor-arg>
</bean>
<bean class="org.opensaml.saml2.metadata.provider.FilesystemMetadataProvider">
<constructor-arg>
<value type="java.io.File">classpath:security/IDP-MetaData.xml</value>
</constructor-arg>
<property name="parserPool" ref="parserPool"/>
</bean>
使用Firefox SAML跟踪器,我可以看到交互工作正常,并且在使用有效的SAML XML数据包对用户进行身份验证后,IDP重定向回我的应用程序(SP)。这并不奇怪,因为此IDP已成功被其他SP使用。 但是,它会重定向到“http://localhost:8080/saml-demo/saml/SSO/alias/myAlias”,这会将以下错误抛给浏览器...
Authentication request failed: org.springframework.security.authentication.AuthenticationServiceException: Error determining metadata contracts
使用Java调试器进一步深入研究代码,我发现真正的错误在代码中更深入。当它看到SP和IDP的相同别名时,它由org.springframework.security.saml.metadata.MetadataManager在第913行抛出。真正的错误是:
MetadataProviderException: Alias myAlias is used both for entity MyEntityId and MyEntityId
除了快速入门指南之外,这个唯一的变化是metadataGeneratorFilter:
<bean id="metadataGeneratorFilter" class="org.springframework.security.saml.metadata.MetadataGeneratorFilter">
<constructor-arg>
<bean class="org.springframework.security.saml.metadata.MetadataGenerator">
<property name="entityId" value="MyEntityId"/>
<property name="signMetadata" value="false"/>
</bean>
</constructor-arg>
</bean>
IDP元数据文件包含......
<md:EntityDescriptor entityID="MyEntityId" xmlns:md="urn:oasis:names:tc:SAML:2.0:metadata">
<md:IDPSSODescriptor WantAuthnRequestsSigned="0" protocolSupportEnumeration="urn:oasis:names:tc:SAML:2.0:protocol">
<md:KeyDescriptor use="signing">
<ds:KeyInfo xmlns:ds="http://www.w3.org/2000/09/xmldsig#">
<ds:X509Data>
<ds:X509Certificate>xxxxxx</ds:X509Certificate>
</ds:X509Data>
</ds:KeyInfo>
</md:KeyDescriptor>
<md:ArtifactResolutionService Binding="urn:oasis:names:tc:SAML:2.0:bindings:SOAP" Location="https://auth.myidp.com/sa1234/" index="0" isDefault="1" />
<md:SingleLogoutService Binding="urn:oasis:names:tc:SAML:2.0:bindings:HTTP-Redirect" Location="https://auth.myidp.com/sa1234/" />
<md:SingleLogoutService Binding="urn:oasis:names:tc:SAML:2.0:bindings:HTTP-POST" Location="https://auth.myidp.com/sa1234/" />
<md:SingleLogoutService Binding="urn:oasis:names:tc:SAML:2.0:bindings:SOAP" Location="https://auth.myidp.com/sa1234/" />
<md:ManageNameIDService Binding="urn:oasis:names:tc:SAML:2.0:bindings:HTTP-Redirect" Location="https://auth.myidp.com/sa1234/" />
<md:ManageNameIDService Binding="urn:oasis:names:tc:SAML:2.0:bindings:HTTP-POST" Location="https://auth.myidp.com/sa1234/" />
<md:ManageNameIDService Binding="urn:oasis:names:tc:SAML:2.0:bindings:SOAP" Location="https://auth.myidp.com/sa1234/" />
<md:SingleSignOnService Binding="urn:oasis:names:tc:SAML:2.0:bindings:HTTP-Redirect" Location="https://auth.myidp.com/sa1234/" />
<md:SingleSignOnService Binding="urn:oasis:names:tc:SAML:2.0:bindings:HTTP-POST" Location="https://auth.myidp.com/sa1234/" />
<md:SingleSignOnService Binding="urn:oasis:names:tc:SAML:2.0:bindings:SOAP" Location="https://auth.myidp.com/sa1234/" />
</md:IDPSSODescriptor>
<md:AttributeAuthorityDescriptor protocolSupportEnumeration="urn:oasis:names:tc:SAML:2.0:protocol">
<md:KeyDescriptor use="signing">
<ds:KeyInfo xmlns:ds="http://www.w3.org/2000/09/xmldsig#">
<ds:X509Data>
<ds:X509Certificate>xxxxxx</ds:X509Certificate>
</ds:X509Data>
</ds:KeyInfo>
</md:KeyDescriptor>
<md:AttributeService Binding="urn:oasis:names:tc:SAML:2.0:bindings:SOAP" Location="https://auth.myidp.com/sa1234/" />
</md:AttributeAuthorityDescriptor>
</md:EntityDescriptor>
以下是MyEntityId_sp.xml的内容:
<?xml version="1.0" encoding="UTF-8"?>
<md:EntityDescriptor xmlns:md="urn:oasis:names:tc:SAML:2.0:metadata"
ID="MyEntityId" entityID="MyEntityId">
<md:SPSSODescriptor AuthnRequestsSigned="true"
WantAssertionsSigned="false" protocolSupportEnumeration="urn:oasis:names:tc:SAML:2.0:protocol">
<md:KeyDescriptor use="signing">
<ds:KeyInfo xmlns:ds="http://www.w3.org/2000/09/xmldsig#">
<ds:X509Data>
<ds:X509Certificate>xxx</ds:X509Certificate>
</ds:X509Data>
</ds:KeyInfo>
</md:KeyDescriptor>
<md:KeyDescriptor use="encryption">
<ds:KeyInfo xmlns:ds="http://www.w3.org/2000/09/xmldsig#">
<ds:X509Data>
<ds:X509Certificate>xxx</ds:X509Certificate>
</ds:X509Data>
</ds:KeyInfo>
</md:KeyDescriptor>
<md:SingleLogoutService
Binding="urn:oasis:names:tc:SAML:2.0:bindings:HTTP-POST"
Location="http://localhost:8080/saml-demo/saml/SingleLogout/alias/myAlias" />
<md:SingleLogoutService
Binding="urn:oasis:names:tc:SAML:2.0:bindings:HTTP-Redirect"
Location="http://localhost:8080/saml-demo/saml/SingleLogout/alias/myAlias" />
<md:NameIDFormat>urn:oasis:names:tc:SAML:1.1:nameid-format:emailAddress
</md:NameIDFormat>
<md:NameIDFormat>urn:oasis:names:tc:SAML:2.0:nameid-format:transient
</md:NameIDFormat>
<md:NameIDFormat>urn:oasis:names:tc:SAML:2.0:nameid-format:persistent
</md:NameIDFormat>
<md:NameIDFormat>urn:oasis:names:tc:SAML:1.1:nameid-format:unspecified
</md:NameIDFormat>
<md:NameIDFormat>urn:oasis:names:tc:SAML:1.1:nameid-format:X509SubjectName
</md:NameIDFormat>
<md:AssertionConsumerService
Binding="urn:oasis:names:tc:SAML:2.0:bindings:HTTP-Artifact"
Location="http://localhost:8080/saml-demo/saml/SSO/alias/myAlias"
index="0" isDefault="true" />
<md:AssertionConsumerService
Binding="urn:oasis:names:tc:SAML:2.0:bindings:HTTP-POST" Location="http://localhost:8080/saml-demo/saml/SSO/alias/myAlias"
index="1" />
</md:SPSSODescriptor>
</md:EntityDescriptor>
答案 0 :(得分:2)
我能够追踪这个问题。
IDP的受众群体限制使用与IDP本身的EntityID相同的ID广告。我可以在IDP元数据文件中看到这一点:
<md:EntityDescriptor entityID="MyEntityId" xmlns:md="urn:oasis:names:tc:SAML:2.0:metadata">
然后使用Firefox SAML跟踪添加,我可以看到IDP包含的最终响应:
<saml:AudienceRestriction> <saml:Audience>MyEntityId</saml:Audience> </saml:AudienceRestriction>
显然,“MyEntityID”不是字面意义上使用的,它是这个应用程序的关键字,在文件的上下文中是有意义的。但是,这意味着我需要为我的SP实体提供与此AudienceRestriction相同的ID,否则我会收到错误。但是,正如Andrew K.所指出的那样,你不能给两个实体提供相同的实体ID。
我不是那个设置IDP服务器的人,所以我无法控制其中一些(而且我提供了IDP元数据文件,所以我只是假设它没有错误)。但是,为了解决这个问题,我只是更改了IDP元数据文件中的entityID。我是SAML的新手,但我认为这不会对我的具体实施产生任何负面影响。