我正在使用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
答案 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并导致整个检查失败的原因。