【发布时间】:2016-04-11 06:32:41
【问题描述】:
我是 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 跟踪器,我可以看到交互工作正常,并且 IDP 在验证用户身份后重定向回我的应用程序(SP),并使用有效的 SAML XML 数据包。这并不奇怪,因为该 IDP 已被其他 SP 成功使用。 但是,它正在重定向到“http://localhost:8080/saml-demo/saml/SSO/alias/myAlias”,这反过来又会向浏览器抛出以下错误...
Authentication request failed: org.springframework.security.authentication.AuthenticationServiceException: Error determining metadata contracts
使用 Java 调试器进一步挖掘代码,我发现真正的错误在代码中更深。当 org.springframework.security.saml.metadata.MetadataManager 看到 SP 和 IDP 的别名相同时,它会在第 913 行抛出。真正的错误是:
MetadataProviderException: Alias myAlias is used both for entity MyEntityId and MyEntityId
除了快速入门指南之外,唯一的其他更改是元数据生成器过滤器:
<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>
【问题讨论】:
-
您不能有两个具有相同标识符的实体。不确定 Spring 是否像某些商业产品一样支持虚拟标识符的概念,这就是为什么这是评论,而不是回答。
-
感谢安德鲁的回复。我将 SP 元数据文件中的 EntityID 更改为其他内容。所以现在 IDP 有一个 EntityID 而 SP 有一个不同的。当我这样做时,我得到了这个错误:“WebSSOProfileConsumerImpl - 我们的实体不是断言的预期受众”。这就是为什么我将它们都配置为相同的 EntityID,我认为它们必须相同。
-
查看 Firefox 中的 SAML 跟踪器,来自 IDP 的最终 SAML 断言确实包含:
MyEntityId -
安德鲁,您的评论实际上是这个问题的答案。我发布了更多详细信息作为答案,以便为遇到此类问题的其他人提供更多详细信息。但是,由于您的评论是正确的,因此您应该得到赞誉,并且为我指明了正确的方向(如果没有其他原因,那么它为我验证了我设置的其他所有内容都是正确的)。如果您将评论移至答案,我会将其标记为解决方案。感谢您的帮助。
标签: spring spring-security saml