Spring Security SAML One登录全局单一注销LogoutRequest解析问题

时间:2015-11-26 05:53:24

标签: spring spring-security saml-2.0 spring-saml

我正在使用One Login实现Spring Security SAML。我已设置所有配置文件和元数据已设置。

如果我从我登录的同一个应用程序注销,我可以获得登录工作和注销工作。在SAML IDP的这个场景中,我得到 LogoutResponse ,Spring Security能够解析和处理它

  

http://localhost:8080/web/saml/SingleLogout?SAMLResponse= ..............

问题是当我登录两个应用程序时,目前我登录到One Login管理控制台,有一个指向我的应用程序的链接,我点击它,我可以直接登录我的应用程序,现在当我从一个登录管理控制台,我的应用程序获得 LogoutRequest

  

http://localhost:8080/web/saml/SingleLogout?SAMLRequest= .........

Spring Security解析它并将对象传递给验证检查逻辑。

org.springframework.security.saml.websso.processLogoutRequest(SAMLMessageContext context, SAMLCredential credential)

此方法有以下检查。

// Make sure request was authenticated if required, authentication is done as part of the binding processing
        if (!context.isInboundSAMLMessageAuthenticated() && context.getLocalExtendedMetadata().isRequireLogoutRequestSigned()) {
            throw new SAMLStatusException(StatusCode.REQUEST_DENIED_URI, "LogoutRequest is required to be signed by the entity policy");
        }

我尝试跟踪跟踪但是上下文对象的字段inboundSAMLMessageAuthenticated永远不会设置为true。上面的检查失败并抛出异常。

在调试模式下,我明确地将值变为true,它继续前进,但还有一个问题。

在同一方法中还有另一项检查。

try {
            // Fail if NameId doesn't correspond to the currently logged user
            NameID nameID = getNameID(context, logoutRequest);
            if (nameID == null || !equalsNameID(credential.getNameID(), nameID)) {
                throw new SAMLStatusException(StatusCode.UNKNOWN_PRINCIPAL_URI, "The requested NameID is invalid");
            }
        } catch (DecryptionException e) {
            throw new SAMLStatusException(StatusCode.RESPONDER_URI, "The NameID can't be decrypted", e);
        }

方法equalsNameId如下。

private boolean equalsNameID(NameID a, NameID b) {
        boolean equals = !differ(a.getSPProvidedID(), b.getSPProvidedID());
        equals = equals && !differ(a.getValue(), b.getValue());
        equals = equals && !differ(a.getFormat(), b.getFormat());
        equals = equals && !differ(a.getNameQualifier(), b.getNameQualifier());
        equals = equals && !differ(a.getSPNameQualifier(), b.getSPNameQualifier());
        equals = equals && !differ(a.getSPProvidedID(), b.getSPProvidedID());
        return equals;
    }
  

这里它在不同的情况下失败(a.getFormat(),b.getFormat())

问题

我不确定是否有一些我遗漏的东西,有点丢失,正是为了解决这个问题。

我对Single Logout的绑定是 HTTP-Redirect

如果提供了指针,我们将不胜感激。如果需要更多信息,请与我们联系。

感谢您的时间。

Stack(旧版应用):

Spring 3.0.6

Spring Security 3.1.2

Spring Security SAML 1.0.0

Tomcat 7.x

1 个答案:

答案 0 :(得分:0)

在原帖后两年遇到这个问题,我不得不做进一步的研究。我仍然有一些关于SAML规范的阅读,但我想我在SAML 2.0勘误表中找到了NameIDType结构的一个条目,它是NameID和Issuer的基础。此类型中的所有四个元素都是可选的。 OneLogin似乎遵循此文档,并且不在SingleLogout请求中发送NameID.Format。

因此,inboundMessage的nameID为null格式,而凭证的nameID格式为“urn:oasis:names:tc:SAML:1.1:nameid-format:emailAddress”。这就是导致getFormat行返回false并导致整个检查失败的原因。