WSO2 和 Spring SAML 单一注销问题
WSO2 and Spring SAML single logout issue
我遇到的问题已在此站点上讨论过多次,但大多数帖子都已经过时了。这是 something similar 我所经历的。我使用 WSO2 IS 5.2 作为我的 IdP,我有 2 个基于 java 的 Web 应用程序托管在参与 SSO 的不同服务器上。每个 webapp (SP) 都实现了 Spring-SAML 扩展。单点登录工作完美,但单点注销只能部分工作。这是测试用例:
- 访问 webapp1 上的安全资源
- 显示来自 Idp (WSO2) 的登录页面并且用户登录
- 已提供来自 webapp1 的安全资源
- 访问 webapp2 上的安全资源
- SAML 请求发送到 Idp,Idp 响应并验证用户
- 已提供来自 webapp2 的安全资源,结束 SSO
- 从 webapp2 启动单点注销
- Webapp2 向 Idp 发送 saml 请求(通过浏览器)并返回 saml 响应
- 用户在 webapp2 上本地注销并且 Idp 会话终止
- IdP 直接向 webapp1(后台通道类型)发送注销请求
- 注销请求到 webapp1 失败(日志指示 SamlStatusException:没有用户登录)
所以最终结果是我在 webapp1 上仍然有一个本地会话。如果我更改顺序并从 webapp1 启动 SLO,则 webapp1 将注销并且 webapp2 的本地会话将继续存在。 WSO2 服务器能够在 SLO 期间确定第二个会话参与者,但是从 Idp 发送到第二个会话参与者的 HTTP 请求没有 Spring 安全上下文。这将是一个无状态的 HTTP 请求,因此不会有登录用户。这就是我认为它失败的原因。
我找到了 this 讨论。它大约 2 岁。这个问题有什么新消息吗?也许我在 WSO2 或 Spring-saml 配置中错过了配置步骤。
这是我的 SP 元数据的相关部分:
<md:SingleLogoutService Location="https://tpap10-wwwdev04.arbfile.org:443/webapp/saml/SingleLogout" Binding="urn:oasis:names:tc:SAML:2.0:bindings:HTTP-POST"/>
<md:SingleLogoutService Location="https://tpap10-wwwdev04.arbfile.org:443/webapp/saml/SingleLogout" Binding="urn:oasis:names:tc:SAML:2.0:bindings:HTTP-Redirect"/>
<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 Location="https://tpap10-wwwdev04.arbfile.org:443/webapp/saml/SSO" Binding="urn:oasis:names:tc:SAML:2.0:bindings:HTTP-POST" isDefault="true" index="0"/>
<md:AssertionConsumerService Location="https://tpap10-wwwdev04.arbfile.org:443/webapp/saml/SSO" Binding="urn:oasis:names:tc:SAML:2.0:bindings:HTTP-Artifact" index="1"/>
一些相关的 Spring-SP 上的 Saml 配置:
<bean id="metadataGeneratorFilter" class="org.springframework.security.saml.metadata.MetadataGeneratorFilter">
<constructor-arg>
<bean class="org.springframework.security.saml.metadata.MetadataGenerator">
<property name="entityId" value="urn:webapp1:mycity"/>
<property name="entityBaseURL" value="https://wwwdev04.domain.org:443/webapp" />
<property name="extendedMetadata">
<bean class="org.springframework.security.saml.metadata.ExtendedMetadata">
<!-- <property name="signMetadata" value="false"/> -->
<property name="idpDiscoveryEnabled" value="false"/>
</bean>
</property>
</bean>
</constructor-arg>
</bean>
WSO2 没有正确实施 SAML 2.0 规范。该规范要求使用 front-end 通道(= 通过用户的浏览器)使用 HTTP-* 绑定的单点注销 - 这使得 HTTP 会话可用并允许 Spring SAML 正确终止它。我相信这个问题在 WSO2 中从未得到解决。
Spring SAML默认使用HttpSession来存储用户状态。这也是 Spring SAML 不支持开箱即用的带有 SOAP 绑定的单点注销的原因。可以实现 application-wide 存储 Spring 安全会话,这些会话可以独立于 HttpSession 失效(因此 work-around WSO2 的限制),但这不是默认配置的(而且我从来没有尝试过)。
我遇到的问题已在此站点上讨论过多次,但大多数帖子都已经过时了。这是 something similar 我所经历的。我使用 WSO2 IS 5.2 作为我的 IdP,我有 2 个基于 java 的 Web 应用程序托管在参与 SSO 的不同服务器上。每个 webapp (SP) 都实现了 Spring-SAML 扩展。单点登录工作完美,但单点注销只能部分工作。这是测试用例:
- 访问 webapp1 上的安全资源
- 显示来自 Idp (WSO2) 的登录页面并且用户登录
- 已提供来自 webapp1 的安全资源
- 访问 webapp2 上的安全资源
- SAML 请求发送到 Idp,Idp 响应并验证用户
- 已提供来自 webapp2 的安全资源,结束 SSO
- 从 webapp2 启动单点注销
- Webapp2 向 Idp 发送 saml 请求(通过浏览器)并返回 saml 响应
- 用户在 webapp2 上本地注销并且 Idp 会话终止
- IdP 直接向 webapp1(后台通道类型)发送注销请求
- 注销请求到 webapp1 失败(日志指示 SamlStatusException:没有用户登录)
所以最终结果是我在 webapp1 上仍然有一个本地会话。如果我更改顺序并从 webapp1 启动 SLO,则 webapp1 将注销并且 webapp2 的本地会话将继续存在。 WSO2 服务器能够在 SLO 期间确定第二个会话参与者,但是从 Idp 发送到第二个会话参与者的 HTTP 请求没有 Spring 安全上下文。这将是一个无状态的 HTTP 请求,因此不会有登录用户。这就是我认为它失败的原因。
我找到了 this 讨论。它大约 2 岁。这个问题有什么新消息吗?也许我在 WSO2 或 Spring-saml 配置中错过了配置步骤。
这是我的 SP 元数据的相关部分:
<md:SingleLogoutService Location="https://tpap10-wwwdev04.arbfile.org:443/webapp/saml/SingleLogout" Binding="urn:oasis:names:tc:SAML:2.0:bindings:HTTP-POST"/>
<md:SingleLogoutService Location="https://tpap10-wwwdev04.arbfile.org:443/webapp/saml/SingleLogout" Binding="urn:oasis:names:tc:SAML:2.0:bindings:HTTP-Redirect"/>
<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 Location="https://tpap10-wwwdev04.arbfile.org:443/webapp/saml/SSO" Binding="urn:oasis:names:tc:SAML:2.0:bindings:HTTP-POST" isDefault="true" index="0"/>
<md:AssertionConsumerService Location="https://tpap10-wwwdev04.arbfile.org:443/webapp/saml/SSO" Binding="urn:oasis:names:tc:SAML:2.0:bindings:HTTP-Artifact" index="1"/>
一些相关的 Spring-SP 上的 Saml 配置:
<bean id="metadataGeneratorFilter" class="org.springframework.security.saml.metadata.MetadataGeneratorFilter">
<constructor-arg>
<bean class="org.springframework.security.saml.metadata.MetadataGenerator">
<property name="entityId" value="urn:webapp1:mycity"/>
<property name="entityBaseURL" value="https://wwwdev04.domain.org:443/webapp" />
<property name="extendedMetadata">
<bean class="org.springframework.security.saml.metadata.ExtendedMetadata">
<!-- <property name="signMetadata" value="false"/> -->
<property name="idpDiscoveryEnabled" value="false"/>
</bean>
</property>
</bean>
</constructor-arg>
</bean>
WSO2 没有正确实施 SAML 2.0 规范。该规范要求使用 front-end 通道(= 通过用户的浏览器)使用 HTTP-* 绑定的单点注销 - 这使得 HTTP 会话可用并允许 Spring SAML 正确终止它。我相信这个问题在 WSO2 中从未得到解决。
Spring SAML默认使用HttpSession来存储用户状态。这也是 Spring SAML 不支持开箱即用的带有 SOAP 绑定的单点注销的原因。可以实现 application-wide 存储 Spring 安全会话,这些会话可以独立于 HttpSession 失效(因此 work-around WSO2 的限制),但这不是默认配置的(而且我从来没有尝试过)。