我们的一个客户要求我们通过SAML实现单次注销(SLO)。他们的SAML服务是身份提供者,而我们的SAML服务是服务提供者。单点登录(SSO)的工作原理是使用客户机的IdP验证用户的凭据,然后将用户重定向到另一个平台上的登录页面,并使用令牌让他们直接登录。该平台完全不了解SAML,特别是不共享SimpleSAMLphp会话状态。
注销需要以两种方式发生:
-
如果用户在我们的平台上点击登出按钮,需要将其登出我们的网站,并点击IdP的SLO服务
-
如果用户点击客户端或其他服务提供商的注销按钮,客户端IdP将点击我们的服务提供商的SLO服务,然后需要将用户从我们的真实平台注销,然后将用户重定向到服务提供商的注销响应页面。
我能够说服我们的平台在注销时将用户重定向到任意页面,所以我认为第一部分可以通过使用SimpleSAML_Auth_Simple::getLogoutURL()
的页面来实现。
当从IdP端命中时,这样的页面也可能工作,但是SAML规范非常复杂,直到我们尝试它之前我无法确定。然而,config/authsources.php
中的SP配置不接受SingleLogoutService
参数;由/www/module.php/saml/sp/metadata.php/entityid
产生的元数据仍然将/www/module.php/saml/sp/saml2-logout.php/entityid
列为SingleLogoutService位置。如果该页面是清除SimpleSAMLphp会话所必需的,那很好,但我需要知道如何插入将用户从我们的平台登录所需的额外重定向。
我试着寻找例子,但我得到的都是API参考。知道如何在不尝试设置自己的IdP的情况下测试注销也很好;是否有像openidp.feide.no
这样的服务可以处理SLO和SSO?
SLO Issue
想象一下这个方案:
Plattform——SP1 IdP SP2,应用
平台和应用程序与simpleSAMLphp SP连接,这也与IdP形成了一个联盟。
必须找到Platffom、app1和app2的正常注销功能并重写:
normal_app_logout() {
// code of the normal logout
....
....
// new code
require_once('<path-to-ssp>/simplesamlphp/lib/_autoload.php'); //load the _autoload.php
$auth = new SimpleSAML_Auth_Simple('default-sp'); // or the auth source you using at your SP
$auth->logout(); <--- call to the SLO
}
这将结束本地会话,连接到该应用程序的SP会话,IdP会话和连接到IdP的SP的SP会话,但…其他应用程序会话发生了什么?它们仍然是活跃的。你想过一个主动调用来结束它,但我认为如果你也覆盖许多应用程序实现的"is_logged_in()"函数会更好。
你必须重写这个函数,并且只有当存在一个有效的SP会话活动时才返回true。
$auth->isAuthenticated()
最近我在wordpress SAML插件上实现了这个功能,检查代码
<标题> 国内流离失所者问题使用Onelogin免费试用版,您可以在那里注册您的SP并使用其IdP。按照本指南配置SAML连接器
但我认为你最好试着自己建立一个IdP。有一个很好的文档和步骤很容易。如果你不想浪费时间配置数据库/ldap,请使用"example-userpass" authsource。
你也可以将你的simplesamlphp实例设置为SP &IdP,但我认为如果你正在学习simplesamlphp最好不要混合。
标题>public function logout()
{
$timeNotOnOrAfter = new 'DateTime();
$timeNow = new 'DateTime();
$timeNotOnOrAfter->add(new DateInterval('PT' . 2 . 'M'));
$context = new 'LightSaml'Model'Context'SerializationContext();
$request = new 'LightSaml'Model'Protocol'LogoutRequest();
$request
->setID('LightSaml'Helper::generateID())
->setIssueInstant($timeNow)
->setDestination($this->_helper->getSloServiceUrl())
->setNotOnOrAfter($timeNotOnOrAfter)
->setIssuer(new 'LightSaml'Model'Assertion'Issuer($this->_helper->getSpEntityId()));
$certificate = 'LightSaml'Credential'X509Certificate::fromFile($this->_helper->getSpCertFile());
$privateKey = 'LightSaml'Credential'KeyHelper::createPrivateKey($this->_helper->getSpPemFile(), '', true);
$request->setSignature(new 'LightSaml'Model'XmlDSig'SignatureWriter($certificate, $privateKey));
$serializationContext = new 'LightSaml'Model'Context'SerializationContext();
$request->serialize($serializationContext->getDocument(), $serializationContext);
$serializationContext->getDocument()->formatOutput = true;
$xml = $serializationContext->getDocument()->saveXML();
Mage::log($xml);
$bindingFactory = new 'LightSaml'Binding'BindingFactory();
$redirectBinding = $bindingFactory->create('LightSaml'SamlConstants::BINDING_SAML2_HTTP_REDIRECT);
$messageContext = new 'LightSaml'Context'Profile'MessageContext();
$messageContext->setMessage($request);
return $redirectBinding->send($messageContext);
}
最后做的事:
$httpResponse = $this->logout();
$this->_redirectUrl($httpResponse->getTargetUrl());