qbnk / php-saml
这是OneLogin PHP SAML工具包的一个克隆版本,修改后支持无缝更改签名证书。
Requires
- php: >=7.3
- ext-dom: *
- phpseclib/phpseclib: ^3.0
- phpseclib/phpseclib2_compat: ~1.0
- robrichards/xmlseclibs: >=3.1.1
Requires (Dev)
- pdepend/pdepend: ^2.8.0
- php-coveralls/php-coveralls: ^2.0
- phploc/phploc: ^4.0 || ^5.0 || ^6.0 || ^7.0
- phpunit/phpunit: ^9.5
- sebastian/phpcpd: ^4.0 || ^5.0 || ^6.0
- squizlabs/php_codesniffer: ^3.5.8
Suggests
- ext-curl: Install curl lib to be able to use the IdPMetadataParser for parsing remote XMLs
- ext-dom: Install xml lib
- ext-openssl: Install openssl lib in order to handle with x509 certs (require to support sign and encryption)
- ext-zlib: Install zlib
- dev-qbank
- v4.1.0
- 4.0.1
- 4.0.0
- v3.4.1.5
- 3.4.1.4
- 3.4.1.3
- 3.4.1.2
- 3.4.1.1
- 3.4.1
- 3.4.0
- 3.3.1
- 3.3.0.2
- 3.3.0.1
- 3.3.0
- 3.2.1.1
- 3.2.1
- 3.2.0
- 3.1.1
- 3.1.0
- v3.0.1
- 3.0.0.x-dev
- v3.0.0
- 2.19.1
- 2.19.0
- 2.18.1
- 2.18.0
- 2.17.1
- 2.17.0
- 2.16.0
- 2.15.0
- v2.14.0
- v2.13.0
- v2.12.0
- 2.11.0
- 2.10.7
- 2.10.6
- 2.10.5
- 2.10.4
- 2.10.3
- 2.10.2
- 2.10.1
- 2.10.0
- 2.9.1
- 2.9.0
- 2.8.0
- 2.7.0
- 2.6.1
- 2.6.0
- 2.5.0
- 2.4.0
- 2.3.0
- 2.1.0
- 2.0.0
- dev-qbank-4.0
- dev-feature/sso-post-binding
This package is auto-updated.
Last update: 2024-09-22 13:49:29 UTC
README
使用此库将SAML支持添加到您的PHP软件中。忘记那些复杂的库,使用由OneLogin Inc.提供和支持的开源库。
警告
版本3.4.0引入了'rejectUnsolicitedResponsesWithInResponseTo'设置参数,默认禁用,允许使未请求的SAMLResponse无效。此版本还将拒绝SAMLResponse,如果提供requestId给验证器但SAMLResponse不包含InResponseTo属性。另外,还有一个额外的设置参数'destinationStrictlyMatches',默认禁用,将强制目标URL严格匹配处理SAMLResponse的地址。
版本3.3.1将xmlseclibs更新到3.0.4(CVE-2019-3465),但php-saml没有直接受到影响,因为它实现了额外的检查,防止利用该漏洞。
版本3.3.0默认启用严格模式
将php-saml更新到3.1.0,此版本包括与XEE攻击相关的安全补丁。
此版本与PHP 7.X兼容,不包括xmlseclibs(您需要通过composer安装它,依赖关系在composer.json中描述)
安全指南
如果您认为您发现了此工具包中的安全漏洞,请带描述报告至 https://www.onelogin.com/security。我们遵循负责任的披露指南,并与您合作迅速找到解决方案。
为什么要在我的软件中添加SAML支持?
SAML是基于XML的用于网络浏览器单点登录的标准,由OASIS安全服务技术委员会定义。该标准自2002年以来一直存在,但最近由于它的优势而变得越来越受欢迎。
- 可用性 - 从门户或内部网一键访问,深度链接,消除密码和自动续订会话,使用户的生活更轻松。
- 安全性 - 基于强大的数字签名进行身份验证和完整性,SAML是一个安全的单点登录协议,全球最大和最注重安全的企业的首选。
- 速度 - SAML很快。只需一个浏览器重定向即可安全地将用户登录到应用程序。
- 钓鱼预防 - 如果您没有应用程序的密码,您就不会被骗在假登录页面上输入它。
- IT友好 - SAML简化了IT的生活,因为它集中了身份验证,提供了更大的可见性,并简化了目录集成。
- 机会 - B2B云服务提供商应支持SAML,以促进其产品的集成。
一般描述
OneLogin的SAML PHP工具包允许您在PHP应用程序上构建SP(服务提供商)并将其连接到任何IdP(身份提供者)。
支持
- SSO和SLO(SP启动和IdP启动)。
- 断言和nameId加密。
- 断言签名。
- 消息签名:AuthNRequest、LogoutRequest、LogoutResponses。
- 启用断言消费者服务端点。
- 启用单一登出服务端点。
- 发布SP元数据(可以签名)。
关键特性
- saml2int - 实现SAML 2.0 Web浏览器SSO配置文件。
- 无会话 - 忘记SP和最终应用程序之间的常见冲突,工具包将委托最终应用程序中的会话。
- 易于使用 - 程序员将被允许进行高级和低级编程,提供了2个易于使用的API。
- 已测试 - 已彻底测试。
- 流行 - OneLogin 的客户在使用它。许多 PHP SAML 插件也在使用它。
使用本指南将您的 PHP 工具包集成到 OneLogin: https://developers.onelogin.com/page/saml-toolkit-for-php
安装
依赖项
php >= 5.4
以及一些核心扩展,如php-xml
、php-date
、php-zlib
。openssl
。安装 openssl 库。它处理 x509 证书。gettext
。安装该库及其 php 驱动程序。它处理翻译。curl
。如果您计划使用 IdP 元数据解析器,请安装该库及其 php 驱动程序。
代码
选项 1. 从 github 克隆仓库
git clone git@github.com:onelogin/php-saml.git
然后拉取 3.X.X 分支/标签
选项 2. 从 github 下载
工具包托管在 github 上。您可以从以下位置下载它:
搜索 3.X.X 版本
将库的核心复制到 PHP 应用程序内部。(每个应用程序都有其结构,因此请花时间找到 PHP SAML 工具包的最佳位置)。请参阅“将 SAML 支持添加到我的应用的指南”以了解详情。
请注意,压缩文件仅包含主要文件。如果您计划使用演示,请使用选项 1。
选项 3. Composer
工具包支持 composer。您可以在 https://packagist.org.cn/packages/onelogin/php-saml 找到 onelogin/php-saml
包。
要将 saml 工具包导入到您的当前 PHP 项目中,请执行
composer require onelogin/php-saml
请记住选择 3.X.X 分支
安装完成后,您将在 vendor/
文件夹中找到一个名为 onelogin
的新文件夹,并在其中找到 php-saml
。请确保您包含 composer 提供的自动加载器。它位于 vendor/autoload.php
。
重要 在此选项中,x509 证书必须存储在 vendor/onelogin/php-saml/certs
中,设置文件存储在 vendor/onelogin/php-saml
中。
当使用 composer update
或类似命令更新包时,您的设置可能会被删除。因此,强烈建议您不要使用设置文件,而是直接将设置作为数组传递给构造函数(本文件稍后解释)。如果您不使用此方法,当使用 composer update
或类似命令更新包时,您的设置可能会被删除。
兼容性
此 3.X.X 支持 PHP 7.X,但也可以与 PHP >=5.4 一起使用(出于安全原因,建议使用 5.6.24+)。
命名空间
如果您正在使用像 Symfony 这样的包含命名空间的框架,请记住,必须通过在开头添加反斜杠(\
)来调用类,例如,要使用静态方法 getSelfURLNoQuery,请使用
\OneLogin\Saml2\Utils::getSelfURLNoQuery()
安全警告
在生产环境中,strict
参数 必须 设置为 "true"
,并且 security
下的 signatureAlgorithm
和 digestAlgorithm
必须设置为除 SHA1 之外的内容(请参阅 https://shattered.io/)。否则,您的环境不安全,将容易受到攻击。
在生产环境中,我们还强烈建议在设置中注册 IdP 证书而不是使用指纹方法。指纹是散列,因此最终容易受到碰撞攻击,这可能导致签名验证绕过。其他 SAML 工具包已弃用该机制,我们保持该机制以保持兼容性,并且也可以在测试环境中使用。
入门指南
了解工具包
新的OneLogin SAML工具包包含不同的文件夹(如certs
、endpoints
、lib
、demo
等)和一些文件。
让我们先描述一下这些文件夹
certs/
SAML需要x509证书来签名和加密如NameID
、Message
、Assertion
、Metadata
等元素。
如果我们的环境需要签名或加密支持,这个文件夹可能包含SP将使用的x509证书和私钥
sp.crt
- SP的公钥证书sp.key
- SP的私钥
或者我们也可以在设置文件中提供这些数据,在$settings['sp']['x509cert']
和$settings['sp']['privateKey']
。
有时我们可能需要在SP发布的元数据上添加签名,在这种情况下,我们可以使用前面提到的x509证书,或者使用新的x.509证书:metadata.crt
和metadata.key
。
如果您正在进行密钥轮换过程并希望在服务提供者元数据上发布该x509证书,请使用sp_new.crt
。
src/
这个文件夹包含了工具包的核心,即库文件
Saml2
文件夹包含后续章节中描述的新版本类和方法。
doc/
这个文件夹包含了工具包的API文档。
endpoints/
工具包有三个端点
metadata.php
- SP元数据的发布位置。acs.php
- 断言消费者服务。处理SAML响应。sls.php
- 单一登出服务。处理登出请求和登出响应。
您可以使用工具包提供的文件,或者在添加SAML支持到您的应用程序时创建自己的端点文件。请注意,这些端点文件使用工具包基本文件夹的设置文件。
locale/
Locale文件夹包含一些翻译:作为概念证明的en_US
和es_ES
。目前还没有翻译,但我们将最终本地化消息并支持多种语言。
其他重要文件
settings_example.php
- 用于创建包含工具包基本配置信息的settings.php文件的模板。advanced_settings_example.php
- 用于创建包含与安全、联系人以及与SP关联的组织的额外配置信息的advanced_settings.php文件的模板。_toolkit_loader.php
- 此文件加载工具包库(SAML2库)。
杂项
tests/
- 包含工具包的单元测试。demo1/
- 包含一个具有SAML支持的简单PHP应用程序的示例。请阅读其中的Readme.txt
以获取更多信息。demo2/
- 包含另一个示例。
工作原理
设置
首先,我们需要配置工具包。SP的信息、IdP的信息,以及在某些情况下,配置高级安全问题,如签名和加密。
有两种方式提供设置信息
- 使用位于工具包基本文件夹中的
settings.php
文件。 - 使用包含设置数据的数组,并将其直接提供给类的构造函数。
有一个模板文件,settings_example.php
,因此您可以复制此文件,重命名并编辑它。
<?php
$settings = array(
// If 'strict' is True, then the PHP Toolkit will reject unsigned
// or unencrypted messages if it expects them to be signed or encrypted.
// Also it will reject the messages if the SAML standard is not strictly
// followed: Destination, NameId, Conditions ... are validated too.
'strict' => true,
// Enable debug mode (to print errors).
'debug' => false,
// Set a BaseURL to be used instead of try to guess
// the BaseURL of the view that process the SAML Message.
// Ex http://sp.example.com/
// http://example.com/sp/
'baseurl' => null,
// Service Provider Data that we are deploying.
'sp' => array(
// Identifier of the SP entity (must be a URI)
'entityId' => '',
// Specifies info about where and how the <AuthnResponse> message MUST be
// returned to the requester, in this case our SP.
'assertionConsumerService' => array(
// URL Location where the <Response> from the IdP will be returned
'url' => '',
// SAML protocol binding to be used when returning the <Response>
// message. OneLogin Toolkit supports this endpoint for the
// HTTP-POST binding only.
'binding' => 'urn:oasis:names:tc:SAML:2.0:bindings:HTTP-POST',
),
// If you need to specify requested attributes, set a
// attributeConsumingService. nameFormat, attributeValue and
// friendlyName can be omitted
"attributeConsumingService"=> array(
"serviceName" => "SP test",
"serviceDescription" => "Test Service",
"requestedAttributes" => array(
array(
"name" => "",
"isRequired" => false,
"nameFormat" => "",
"friendlyName" => "",
"attributeValue" => array()
)
)
),
// Specifies info about where and how the <Logout Response> message MUST be
// returned to the requester, in this case our SP.
'singleLogoutService' => array(
// URL Location where the <Response> from the IdP will be returned
'url' => '',
// SAML protocol binding to be used when returning the <Response>
// message. OneLogin Toolkit supports the HTTP-Redirect binding
// only for this endpoint.
'binding' => 'urn:oasis:names:tc:SAML:2.0:bindings:HTTP-Redirect',
),
// Specifies the constraints on the name identifier to be used to
// represent the requested subject.
// Take a look on lib/Saml2/Constants.php to see the NameIdFormat supported.
'NameIDFormat' => 'urn:oasis:names:tc:SAML:1.1:nameid-format:emailAddress',
// Usually x509cert and privateKey of the SP are provided by files placed at
// the certs folder. But we can also provide them with the following parameters
'x509cert' => '',
'privateKey' => '',
/*
* Key rollover
* If you plan to update the SP x509cert and privateKey
* you can define here the new x509cert and it will be
* published on the SP metadata so Identity Providers can
* read them and get ready for rollover.
*/
// 'x509certNew' => '',
),
// Identity Provider Data that we want connected with our SP.
'idp' => array(
// Identifier of the IdP entity (must be a URI)
'entityId' => '',
// SSO endpoint info of the IdP. (Authentication Request protocol)
'singleSignOnService' => array(
// URL Target of the IdP where the Authentication Request Message
// will be sent.
'url' => '',
// SAML protocol binding to be used when returning the <Response>
// message. OneLogin Toolkit supports the HTTP-Redirect binding
// only for this endpoint.
'binding' => 'urn:oasis:names:tc:SAML:2.0:bindings:HTTP-Redirect',
),
// SLO endpoint info of the IdP.
'singleLogoutService' => array(
// URL Location of the IdP where SLO Request will be sent.
'url' => '',
// URL location of the IdP where SLO Response will be sent (ResponseLocation)
// if not set, url for the SLO Request will be used
'responseUrl' => '',
// SAML protocol binding to be used when returning the <Response>
// message. OneLogin Toolkit supports the HTTP-Redirect binding
// only for this endpoint.
'binding' => 'urn:oasis:names:tc:SAML:2.0:bindings:HTTP-Redirect',
),
// Public x509 certificate of the IdP
'x509cert' => '',
/*
* Instead of use the whole x509cert you can use a fingerprint in order to
* validate a SAMLResponse, but we don't recommend to use that
* method on production since is exploitable by a collision attack.
* (openssl x509 -noout -fingerprint -in "idp.crt" to generate it,
* or add for example the -sha256 , -sha384 or -sha512 parameter)
*
* If a fingerprint is provided, then the certFingerprintAlgorithm is required in order to
* let the toolkit know which algorithm was used. Possible values: sha1, sha256, sha384 or sha512
* 'sha1' is the default value.
*
* Notice that if you want to validate any SAML Message sent by the HTTP-Redirect binding, you
* will need to provide the whole x509cert.
*/
// 'certFingerprint' => '',
// 'certFingerprintAlgorithm' => 'sha1',
/* In some scenarios the IdP uses different certificates for
* signing/encryption, or is under key rollover phase and
* more than one certificate is published on IdP metadata.
* In order to handle that the toolkit offers that parameter.
* (when used, 'x509cert' and 'certFingerprint' values are
* ignored).
*/
// 'x509certMulti' => array(
// 'signing' => array(
// 0 => '<cert1-string>',
// ),
// 'encryption' => array(
// 0 => '<cert2-string>',
// )
// ),
),
);
除了必需的设置数据(IdP、SP)之外,还可以定义额外信息。与基本信息的模板一样,在工具包基本文件夹中还有一个用于高级信息的模板,名为advanced_settings_example.php
,您可以复制并重命名为advanced_settings.php
。
<?php
$advancedSettings = array(
// Compression settings
'compress' => array(
'requests' => true,
'responses' => true
),
// Security settings
'security' => array(
/** signatures and encryptions offered */
// Indicates that the nameID of the <samlp:logoutRequest> sent by this SP
// will be encrypted.
'nameIdEncrypted' => false,
// Indicates whether the <samlp:AuthnRequest> messages sent by this SP
// will be signed. [Metadata of the SP will offer this info]
'authnRequestsSigned' => false,
// Indicates whether the <samlp:logoutRequest> messages sent by this SP
// will be signed.
'logoutRequestSigned' => false,
// Indicates whether the <samlp:logoutResponse> messages sent by this SP
// will be signed.
'logoutResponseSigned' => false,
/* Sign the Metadata
False || True (use sp certs) || array (
'keyFileName' => 'metadata.key',
'certFileName' => 'metadata.crt'
)
|| array (
'x509cert' => '',
'privateKey' => ''
)
*/
'signMetadata' => false,
/** signatures and encryptions required **/
// Indicates a requirement for the <samlp:Response>, <samlp:LogoutRequest>
// and <samlp:LogoutResponse> elements received by this SP to be signed.
'wantMessagesSigned' => false,
// Indicates a requirement for the <saml:Assertion> elements received by
// this SP to be encrypted.
'wantAssertionsEncrypted' => false,
// Indicates a requirement for the <saml:Assertion> elements received by
// this SP to be signed. [Metadata of the SP will offer this info]
'wantAssertionsSigned' => false,
// Indicates a requirement for the NameID element on the SAMLResponse
// received by this SP to be present.
'wantNameId' => true,
// Indicates a requirement for the NameID received by
// this SP to be encrypted.
'wantNameIdEncrypted' => false,
// Authentication context.
// Set to false and no AuthContext will be sent in the AuthNRequest.
// Set true or don't present this parameter and you will get an AuthContext 'exact' 'urn:oasis:names:tc:SAML:2.0:ac:classes:PasswordProtectedTransport'.
// Set an array with the possible auth context values: array('urn:oasis:names:tc:SAML:2.0:ac:classes:Password', 'urn:oasis:names:tc:SAML:2.0:ac:classes:X509').
'requestedAuthnContext' => true,
// Indicates if the SP will validate all received xmls.
// (In order to validate the xml, 'strict' and 'wantXMLValidation' must be true).
'wantXMLValidation' => true,
// If true, SAMLResponses with an empty value at its Destination
// attribute will not be rejected for this fact.
'relaxDestinationValidation' => false,
// If true, Destination URL should strictly match to the address to
// which the response has been sent.
// Notice that if 'relaxDestinationValidation' is true an empty Destintation
// will be accepted.
'destinationStrictlyMatches' => false,
// If true, SAMLResponses with an InResponseTo value will be rejectd if not
// AuthNRequest ID provided to the validation method.
'rejectUnsolicitedResponsesWithInResponseTo' => false,
// Algorithm that the toolkit will use on signing process. Options:
// 'http://www.w3.org/2000/09/xmldsig#rsa-sha1'
// 'http://www.w3.org/2000/09/xmldsig#dsa-sha1'
// 'http://www.w3.org/2001/04/xmldsig-more#rsa-sha256'
// 'http://www.w3.org/2001/04/xmldsig-more#rsa-sha384'
// 'http://www.w3.org/2001/04/xmldsig-more#rsa-sha512'
// Notice that rsa-sha1 is a deprecated algorithm and should not be used
'signatureAlgorithm' => 'http://www.w3.org/2001/04/xmldsig-more#rsa-sha256',
// Algorithm that the toolkit will use on digest process. Options:
// 'http://www.w3.org/2000/09/xmldsig#sha1'
// 'http://www.w3.org/2001/04/xmlenc#sha256'
// 'http://www.w3.org/2001/04/xmldsig-more#sha384'
// 'http://www.w3.org/2001/04/xmlenc#sha512'
// Notice that sha1 is a deprecated algorithm and should not be used
'digestAlgorithm' => 'http://www.w3.org/2001/04/xmlenc#sha256',
// ADFS URL-Encodes SAML data as lowercase, and the toolkit by default uses
// uppercase. Turn it True for ADFS compatibility on signature verification
'lowercaseUrlencoding' => false,
),
// Contact information template, it is recommended to supply a
// technical and support contacts.
'contactPerson' => array(
'technical' => array(
'givenName' => '',
'emailAddress' => ''
),
'support' => array(
'givenName' => '',
'emailAddress' => ''
),
),
// Organization information template, the info in en_US lang is
// recomended, add more if required.
'organization' => array(
'en-US' => array(
'name' => '',
'displayname' => '',
'url' => ''
),
),
);
压缩设置允许您指示身份提供者(IdP)是否可以接受使用 gzip('请求' 和 '响应')压缩的数据。但如果我们在 getRequest
或 getResponse
方法中提供了一个 $deflate
布尔参数,它将优先于压缩设置。
在安全部分,您可以设置服务提供者(SP)处理消息和断言的方式。联系 IdP 的管理员,询问 IdP 的期望值,并决定 SP 将进行哪些验证以及 SP 将有哪些要求,并将这些信息传达给 IdP 的管理员。
一旦我们知道了可以配置的数据类型,让我们谈谈设置在工具包中的处理方式。
描述的设置文件(settings.php
和 advanced_settings.php
)在工具包构造函数中没有提供其他设置信息数组时将被工具包加载。让我们看看一些例子。
// Initializes toolkit with settings.php & advanced_settings files.
$auth = new OneLogin\Saml2\Auth();
//or
$settings = new OneLogin\Saml2\Settings();
// Initializes toolkit with the array provided.
$auth = new OneLogin\Saml2\Auth($settingsInfo);
//or
$settings = new OneLogin\Saml2\Settings($settingsInfo);
您可以在包含构造函数执行的文件中声明 $settingsInfo
,或者在任何文件中定位它们,并按以下示例加载该文件以获取可用数组。
<?php
require_once 'custom_settings.php'; // The custom_settings.php contains a
// $settingsInfo array.
$auth = new OneLogin\Saml2\Auth($settingsInfo);
如何加载库
为了使用工具包库,如果您的项目支持 composer,您只需使用 composer 安装它(见安装部分)即可完成。
如果您的项目不使用 composer,您需要导入位于工具包基本文件夹中的 _toolkit_loader.php
文件。您可以按以下方式加载此文件。
<?php
define("TOOLKIT_PATH", '/var/www/php-saml/');
require_once(TOOLKIT_PATH . '_toolkit_loader.php');
在这行之后,我们将能够使用工具包的类(及其方法)(因为外部和 Saml2 库文件已加载)。
该工具包依赖于 xmlseclibs 3.X.X 分支,您需要获取其代码并将其放置在您的项目中,并使用 _toolkit_loader.php 文件包含 xmlseclibs。
启动单点登录(SSO)
为了向 IdP 发送 AuthNRequest
<?php
define("TOOLKIT_PATH", '/var/www/php-saml/');
require_once(TOOLKIT_PATH . '_toolkit_loader.php'); // We load the SAML2 lib
$auth = new OneLogin\Saml2\Auth(); // Constructor of the SP, loads settings.php
// and advanced_settings.php
$auth->login(); // Method that sent the AuthNRequest
根据 advanced_settings.php
('authnRequestsSigned'
)的安全信息,AuthNRequest
将以签名或未签名的方式发送。
然后 IdP 将将 SAML 响应返回给用户的客户端。客户端随后将带有此信息转发到 SP 的属性消费者服务。如果我们没有在登录方法中设置 'url'
参数,并且我们使用工具包提供的默认 ACS(endpoints/acs.php
),则 ACS 终端将用户重定向到启动 SSO 请求的文件。
我们可以设置一个 'returnTo'
URL 以更改工作流程,并将用户重定向到其他 PHP 文件。
$newTargetUrl = 'http://example.com/consume2.php';
$auth = new OneLogin\Saml2\Auth();
$auth->login($newTargetUrl);
登录方法可以接收其他六个可选参数
$parameters
- 一个数组,其中包含将在 HTTP-Redirect 中的GET
中添加的参数。$forceAuthn
- 当为 true 时,AuthNRequest
将设置ForceAuthn='true'
$isPassive
- 当为 true 时,AuthNRequest
将设置Ispassive='true'
$strict
- 如果我们想保持(返回 URL 字符串),则为 true,如果我们要重定向,则为 false$setNameIdPolicy
- 当为 true 时,AuthNRequest 将设置一个 nameIdPolicy 元素。$nameIdValueReq
- 指示 IdP 应该认证的主体。
如果需要在将来 SAMLResponse ID 和要发送的 AuthNRequest ID 之间进行匹配,则必须提取并保存该 AuthNRequest ID。
$ssoBuiltUrl = $auth->login(null, array(), false, false, true);
$_SESSION['AuthNRequestID'] = $auth->getLastRequestID();
header('Pragma: no-cache');
header('Cache-Control: no-cache, must-revalidate');
header('Location: ' . $ssoBuiltUrl);
exit();
SP 终端
与 SP 相关有三个重要的视图:元数据视图、ACS 视图和 SLS 视图。工具包在 endpoints 目录中提供了这些视图的示例。
SP 元数据 endpoints/metadata.php
此代码将根据我们在设置文件中提供的信息,提供我们SP的XML元数据文件。
<?php
define("TOOLKIT_PATH", '/var/www/php-saml/');
require_once dirname(TOOLKIT_PATH.'/_toolkit_loader.php';
try {
$auth = new OneLogin\Saml2\Auth();
$settings = $auth->getSettings();
$metadata = $settings->getSPMetadata();
$errors = $settings->validateMetadata($metadata);
if (empty($errors)) {
header('Content-Type: text/xml');
echo $metadata;
} else {
throw new OneLogin\Saml2\Error(
'Invalid SP metadata: '.implode(', ', $errors),
OneLogin\Saml2\Error::METADATA_SP_INVALID
);
}
} catch (Exception $e) {
echo $e->getMessage();
}
getSPMetadata
将根据advanced_settings.php
('signMetadata'
)中的安全信息返回签名或未签名的元数据。
在暴露XML元数据之前,会进行检查以确保提供的信息有效。
除了使用Auth对象,您可以直接使用以下方法
$settings = new OneLogin\Saml2\Settings($settingsInfo, true);
来获取设置对象,并使用true参数,我们将避免进行IdP设置验证。
属性消费者服务(ACS)endpoints/acs.php
此代码处理IdP通过用户的客户端转发给SP的SAML响应。
<?php
session_start(); // IMPORTANT: This is required in order to be able
// to store the user data in the session.
define("TOOLKIT_PATH", '/var/www/php-saml/');
require_once dirname(TOOLKIT_PATH.'/_toolkit_loader.php';
$auth = new OneLogin\Saml2\Auth();
if (isset($_SESSION) && isset($_SESSION['AuthNRequestID'])) {
$requestID = $_SESSION['AuthNRequestID'];
} else {
$requestID = null;
}
$auth->processResponse($requestID);
unset($_SESSION['AuthNRequestID']);
$errors = $auth->getErrors();
if (!empty($errors)) {
echo '<p>' . implode(', ', $errors) . '</p>';
exit();
}
if (!$auth->isAuthenticated()) {
echo "<p>Not authenticated</p>";
exit();
}
$_SESSION['samlUserdata'] = $auth->getAttributes();
$_SESSION['samlNameId'] = $auth->getNameId();
$_SESSION['samlNameIdFormat'] = $auth->getNameIdFormat();
$_SESSION['samlNameidNameQualifier'] = $auth->getNameIdNameQualifier();
$_SESSION['samlNameidSPNameQualifier'] = $auth->getNameIdSPNameQualifier();
$_SESSION['samlSessionIndex'] = $auth->getSessionIndex();
if (isset($_POST['RelayState']) && OneLogin\Saml2\Utils::getSelfURL() != $_POST['RelayState']) {
$auth->redirectTo($_POST['RelayState']);
}
$attributes = $_SESSION['samlUserdata'];
$nameId = $_SESSION['samlNameId'];
echo '<h1>Identified user: '. htmlentities($nameId) .'</h1>';
if (!empty($attributes)) {
echo '<h2>' . _('User attributes:') . '</h2>';
echo '<table><thead><th>' . _('Name') . '</th><th>' . _('Values') . '</th></thead><tbody>';
foreach ($attributes as $attributeName => $attributeValues) {
echo '<tr><td>' . htmlentities($attributeName) . '</td><td><ul>';
foreach ($attributeValues as $attributeValue) {
echo '<li>' . htmlentities($attributeValue) . '</li>';
}
echo '</ul></td></tr>';
}
echo '</tbody></table>';
} else {
echo _('No attributes found.');
}
处理SAML响应,并检查是否存在错误。它还验证用户是否已认证,并将userdata存储在会话中。
在此阶段,有两种可能的方案
如果没有提供
RelayState
,我们可以显示用户数据在此视图或我们想要的任何方式。如果提供了
RelayState
,将进行重定向。
注意,我们在重定向之前将用户数据保存在会话中,以便在RelayState
视图中可用。
getAttributes
方法
为了检索属性,我们可以使用以下方法
$attributes = $auth->getAttributes();
使用此方法,我们获取SAML响应断言中IdP提供的所有用户数据。
如果我们执行`
print_r($attributes)`
,我们可能会得到
Array
(
[cn] => Array
(
[0] => John
)
[sn] => Array
(
[0] => Doe
)
[mail] => Array
(
[0] => john.doe@example.com
)
[groups] => Array
(
[0] => users
[1] => members
)
)
每个属性名称都可以用作$attributes
的索引以获取值。每个属性值都是一个数组 - 单值属性是一个只有一个元素的数组。
以下代码是等效的
$attributes = $auth->getAttributes();
print_r($attributes['cn']);
print_r($auth->getAttribute('cn'));
在尝试获取属性之前,检查用户是否已认证。如果用户未认证或SAML断言中没有属性,则将返回空数组。例如,如果我们调用getAttributes
在$auth->processResponse
之前,则getAttributes()
将返回空数组。
单一登出服务(SLS)endpoints/sls.php
此代码处理登出请求和登出响应。
<?php
session_start(); // IMPORTANT: This is required in order to be able
// to close the user session.
define("TOOLKIT_PATH", '/var/www/php-saml/');
require_once dirname(TOOLKIT_PATH.'/_toolkit_loader.php';
$auth = new OneLogin\Saml2\Auth();
if (isset($_SESSION) && isset($_SESSION['LogoutRequestID'])) {
$requestID = $_SESSION['LogoutRequestID'];
} else {
$requestID = null;
}
$auth->processSLO(false, $requestID);
$errors = $auth->getErrors();
if (empty($errors)) {
echo 'Sucessfully logged out';
} else {
echo implode(', ', $errors);
}
如果SLS端点收到登出响应,将验证响应并可能关闭会话
// part of the processSLO method
$logoutResponse = new OneLogin\Saml2\LogoutResponse($this->_settings, $_GET['SAMLResponse']);
if (!$logoutResponse->isValid($requestId)) {
$this->_errors[] = 'invalid_logout_response';
} else if ($logoutResponse->getStatus() !== OneLogin\Saml2\Constants::STATUS_SUCCESS) {
$this->_errors[] = 'logout_not_success';
} else {
if (!$keepLocalSession) {
OneLogin\Saml2\Utils::deleteLocalSession();
}
}
如果SLS端点收到登出请求,将验证请求,关闭会话并向IdP的SLS端点发送登出响应。
// part of the processSLO method
$decoded = base64_decode($_GET['SAMLRequest']);
$request = gzinflate($decoded);
if (!OneLogin\Saml2\LogoutRequest::isValid($this->_settings, $request)) {
$this->_errors[] = 'invalid_logout_request';
} else {
if (!$keepLocalSession) {
OneLogin\Saml2\Utils::deleteLocalSession();
}
$inResponseTo = $request->id;
$responseBuilder = new OneLogin\Saml2\LogoutResponse($this->_settings);
$responseBuilder->build($inResponseTo);
$logoutResponse = $responseBuilder->getResponse();
$parameters = array('SAMLResponse' => $logoutResponse);
if (isset($_GET['RelayState'])) {
$parameters['RelayState'] = $_GET['RelayState'];
}
$security = $this->_settings->getSecurityData();
if (isset($security['logoutResponseSigned']) && $security['logoutResponseSigned']) {
$signature = $this->buildResponseSignature($logoutResponse, $parameters['RelayState'], $security['signatureAlgorithm']);
$parameters['SigAlg'] = $security['signatureAlgorithm'];
$parameters['Signature'] = $signature;
}
$this->redirectTo($this->getSLOurl(), $parameters);
}
如果您不是使用默认的PHP会话,或者需要其他手动销毁会话的方法,您可以将回调方法传递给processSLO
方法的第四个参数
$keepLocalSession = False;
$callback = function () {
// Destroy user session
};
$auth->processSLO($keepLocalSession, null, false, $callback);
如果我们不希望processSLO
销毁会话,请将true参数传递给processSLO
方法
$keepLocalSession = True;
$auth->processSLO($keepLocalSession);
启动SLO
为了向IdP发送登出请求
<?php
define("TOOLKIT_PATH", '/var/www/php-saml/');
require_once(TOOLKIT_PATH . '_toolkit_loader.php');
$auth = new OneLogin\Saml2\Auth();
$auth->logout(); // Method that sent the Logout Request.
还有八个可选参数可以设置
$returnTo
- 用户登出后应返回的目标URL。$parameters
- 要添加到GET中的额外参数。$name_id
- 将用于构建登出请求。如果未设置name_id
参数且auth对象处理了包含NameId
的SAML响应,则将使用此NameId
。$session_index
- 用于标识用户会话的SessionIndex。$stay
- 如果我们想停留(返回URL字符串),则为true;如果为假,则重定向。$nameIdFormat
- 将在登出请求中设置NameID格式。$nameIdNameQualifier
- 将在登出请求中设置NameID NameQualifier。$nameIdSPNameQualifier
- 将在登出请求中设置NameID SP NameQualifier。
根据advanced_settings.php
('logoutRequestSigned'
)中的安全信息,登出请求将签名或未签名。
身份提供者(IdP)将通过用户的客户端将注销响应发送到服务提供者(SP)的单点登出服务。如果我们没有在注销方法中设置'url'
参数,并且使用工具包提供的默认SLS(endpoints/sls.php
),则SLS端点将重定向用户到启动SLO请求的文件。
我们可以设置一个'returnTo'
URL来更改工作流程并将用户重定向到其他PHP文件。
$newTargetUrl = 'http://example.com/loggedOut.php';
$auth = new OneLogin\Saml2\Auth();
$auth->logout($newTargetUrl);
带有所有参数的更复杂注销
$auth = new OneLogin\Saml2\Auth();
$returnTo = null;
$parameters = array();
$nameId = null;
$sessionIndex = null;
$nameIdFormat = null;
$nameIdNameQualifier = null;
$nameIdSPNameQualifier = null;
if (isset($_SESSION['samlNameId'])) {
$nameId = $_SESSION['samlNameId'];
}
if (isset($_SESSION['samlSessionIndex'])) {
$sessionIndex = $_SESSION['samlSessionIndex'];
}
if (isset($_SESSION['samlNameIdFormat'])) {
$nameIdFormat = $_SESSION['samlNameIdFormat'];
}
if (isset($_SESSION['samlNameIdNameQualifier'])) {
$nameIdNameQualifier = $_SESSION['samlNameIdNameQualifier'];
}
if (isset($_SESSION['samlNameIdSPNameQualifier'])) {
$nameIdSPNameQualifier = $_SESSION['samlNameIdSPNameQualifier'];
}
$auth->logout($returnTo, $parameters, $nameId, $sessionIndex, false, $nameIdFormat, $nameIdNameQualifier, $nameIdSPNameQualifier);
如果需要将未来的注销响应ID与要发送的注销请求ID进行匹配,则必须提取并存储该注销请求ID。
$sloBuiltUrl = $auth->logout(null, $parameters, $nameId, $sessionIndex, true);
$_SESSION['LogoutRequestID'] = $auth->getLastRequestID();
header('Pragma: no-cache');
header('Cache-Control: no-cache, must-revalidate');
header('Location: ' . $sloBuiltUrl);
exit();
初始化SSO请求并处理响应的视图示例(是acs目标)
我们可以编写一个独特的文件来启动SSO流程,处理响应,获取属性,启动SLO并处理注销响应。
注意:请查看包含该用例的demo1
文件夹;在后面的部分中,我们将更详细地解释demo1用例。
<?php
session_start(); // Initialize the session, we do that because
// Note that processResponse and processSLO
// methods could manipulate/close that session
require_once dirname(__DIR__) . '/_toolkit_loader.php'; // Load Saml2 and xmlseclibs
require_once 'settings.php'; // Load the setting info as an Array
$auth = new OneLogin\Saml2\Auth($settingsInfo); // Initialize the SP SAML instance
if (isset($_GET['sso'])) { // SSO action. Will send an AuthNRequest to the IdP
$auth->login();
} else if (isset($_GET['sso2'])) { // Another SSO action
$returnTo = $spBaseUrl.'/demo1/attrs.php'; // but set a custom RelayState URL
$auth->login($returnTo);
} else if (isset($_GET['slo'])) { // SLO action. Will sent a Logout Request to IdP
$auth->logout();
} else if (isset($_GET['acs'])) { // Assertion Consumer Service
$auth->processResponse(); // Process the Response of the IdP, get the
// attributes and put then at
// $_SESSION['samlUserdata']
$errors = $auth->getErrors(); // This method receives an array with the errors
// that could took place during the process
if (!empty($errors)) {
echo '<p>' . implode(', ', $errors) . '</p>';
}
// This check if the response was
if (!$auth->isAuthenticated()) { // sucessfully validated and the user
echo '<p>Not authenticated</p>'; // data retrieved or not
exit();
}
$_SESSION['samlUserdata'] = $auth->getAttributes(); // Retrieves user data
if (isset($_POST['RelayState']) && OneLogin\Saml2\Utils::getSelfURL() != $_POST['RelayState']) {
$auth->redirectTo($_POST['RelayState']); // Redirect if there is a
} // relayState set
} else if (isset($_GET['sls'])) { // Single Logout Service
$auth->processSLO(); // Process the Logout Request & Logout Response
$errors = $auth->getErrors(); // Retrieves possible validation errors
if (empty($errors)) {
echo '<p>Sucessfully logged out</p>';
} else {
echo '<p>' . implode(', ', $errors) . '</p>';
}
}
if (isset($_SESSION['samlUserdata'])) { // If there is user data we print it.
if (!empty($_SESSION['samlUserdata'])) {
$attributes = $_SESSION['samlUserdata'];
echo 'You have the following attributes:<br>';
echo '<table><thead><th>Name</th><th>Values</th></thead><tbody>';
foreach ($attributes as $attributeName => $attributeValues) {
echo '<tr><td>' . htmlentities($attributeName) . '</td><td><ul>';
foreach ($attributeValues as $attributeValue) {
echo '<li>' . htmlentities($attributeValue) . '</li>';
}
echo '</ul></td></tr>';
}
echo '</tbody></table>';
} else { // If there is not user data, we notify
echo "<p>You don't have any attribute</p>";
}
echo '<p><a href="?slo" >Logout</a></p>'; // Print some links with possible
} else { // actions
echo '<p><a href="?sso" >Login</a></p>';
echo '<p><a href="?sso2" >Login and access to attrs.php page</a></p>';
}
URL猜测方法
php-saml工具包在OneLogin\Saml2\Utils中使用一系列方法来猜测处理SAML消息的URL。
getSelfHost
返回当前主机。getSelfPort
返回请求使用的端口号。isHTTPS
检查协议是https还是http。getSelfURLhost
返回协议 + 当前主机 + 端口(如果不同于常用端口)。getSelfURL
返回当前主机 + 当前视图 + 查询。getSelfURLNoQuery
返回当前主机 + 当前视图的URL。getSelfRoutedURLNoQuery
返回当前主机 + 当前视图的路由URL。
getSelfURLNoQuery和getSelfRoutedURLNoQuery用于计算当前URL,以便验证SAML元素,如目的地或收件人。
当PHP应用程序位于代理或负载均衡器后面时,我们可以执行setProxyVars(true)
和setSelfPort
,并且isHTTPS
将负责处理$_SERVER["HTTP_X_FORWARDED_PORT"]
和$_SERVER['HTTP_X_FORWARDED_PROTO']
变量(否则它们将被忽略)。
此外,开发人员可以使用setSelfProtocol
、setSelfHost
、setSelfPort
和getBaseURLPath
来定义要由isHTTPS
、getSelfHost
、getSelfPort
和getBaseURLPath
返回的特定值。并定义一个setBasePath
,用于在getSelfURL
和getSelfRoutedURLNoQuery
中使用,以替换从$_SERVER["REQUEST_URI"]
中提取的数据。
在设置中,开发人员将能够设置一个'baseurl'
参数,该参数将自动使用setBaseURL
来设置setSelfProtocol
、setSelfHost
、setSelfPort
和setBaseURLPath
的值。
在负载均衡器后面工作
当在带有SSL卸载的负载均衡器后面工作时,断言请求URL和SAML响应的目的地属性可能会失败。
您可以通过配置服务器使其了解代理并返回请求的原URL来解决这个问题。
或者,可以使用前面部分中描述的方法。
SP密钥轮换
如果您计划更新SP的x509cert和privateKey,您可以定义新的x509cert为$settings['sp']['x509certNew']
,它将发布在SP元数据中,以便身份提供者可以读取它们并准备轮换。
具有多个证书的IdP
在某些场景中,IdP使用不同的证书进行签名/加密,或者处于密钥轮换阶段,并且多个证书已发布在IdP元数据中。
为了处理这种情况,工具包提供了$settings['idp']['x509certMulti']
参数。
当使用该参数时,工具包将忽略'x509cert'
和'certFingerprint'
值。
x509certMulti
是一个包含2个键的数组
signing
。一个包含证书的数组,用于验证IdP签名encryption
。一个包含一个唯一证书的数组,用于加密发送给IdP的数据
重放攻击
为了避免重放攻击,您可以存储已处理SAML消息的ID,以避免重复处理。由于消息会过期并且由于这个事实而失效,因此您不需要存储这些ID超过您目前接受的时效。
使用Auth对象的getLastMessageId
/getLastAssertionId
方法获取最后处理的消息/断言的ID。
主要类和方法
下面描述了可以调用的主要类和方法。
Saml2库
现在让我们描述SAML2库的类和方法。
OneLogin\Saml2\Auth - Auth.php
OneLogin PHP工具包的主要类
Auth
- 初始化SP SAML实例login
- 启动SSO流程。logout
- 启动SLO流程。processResponse
- 处理IdP发送的SAML响应。processSLO
- 处理IdP发送的SAML注销响应/注销请求。redirectTo
- 将用户重定向到通过参数传递的URL或我们定义的SSO请求的URL。isAuthenticated
- 检查用户是否已认证。getAttributes
- 返回SAML属性的集合。getAttribute
- 返回请求的SAML属性getNameId
- 返回nameIDgetNameIdFormat
- 获取IdP提供的NameID格式。getNameIdNameQualifier
- 获取SAML响应字符串提供的NameID NameQualifier。getNameIdNameSPQualifier
- 获取SAML响应字符串提供的NameID SP NameQualifier。getSessionIndex
- 从AuthnStatement获取SessionIndex。getErrors
- 返回是否有错误getSSOurl
- 获取SSO URL。getSLOurl
- 获取SLO URL。getLastRequestID
- 生成到最后一个请求SAML消息的ID。buildRequestSignature
- 为SAML请求生成签名buildResponseSignature
- 为SAML响应生成签名getSettings
- 返回设置信息setStrict
- 设置严格模式激活/禁用getLastRequestID
- 获取由服务提供商生成的最后一个AuthNRequest或LogoutRequest的ID。getLastRequestXML
- 返回最近构造/处理的XML SAML请求(AuthNRequest,LogoutRequest)getLastResponseXML
- 返回最近构造/处理的XML SAML响应(SAMLResponse,LogoutResponse)。如果SAMLResponse包含加密的断言,则解密它。
OneLogin\Saml2\AuthnRequest - AuthnRequest.php
SAML 2认证请求类
AuthnRequest
- 构造AuthnRequest
对象。getRequest
- 返回压缩、base64编码、未签名的AuthnRequest
。getId
- 返回AuthNRequest
ID。getXML
- 返回作为请求一部分发送的XML。
OneLogin\Saml2\Response - Response.php
SAML 2认证响应类
Response
- 构造SAML响应对象。isValid
- 使用证书确定SAML响应是否有效。checkStatus
- 检查状态是否成功。getAudiences
- 获取受众。getIssuers
- 获取发行者(从响应和断言中获取)getNameIdData
- 从IdP的SAML响应中获取NameID数据。getNameId
- 从IdP的SAML响应中获取NameID。getNameIdFormat
- 获取IdP提供的NameID格式。getNameIdNameQualifier
- 获取SAML响应字符串提供的NameID NameQualifier。getNameIdNameSPQualifier
- 获取SAML响应字符串提供的NameID SP NameQualifier。getSessionNotOnOrAfter
- 从AuthnStatement中获取SessionNotOnOrAfter。getSessionIndex
- 从AuthnStatement获取SessionIndex。getAttributes
- 从AttributeStatement元素中获取属性。validateNumAssertions
- 验证文档只包含一个断言(加密或未加密)。validateTimestamps
- 验证文档根据条件元素仍然有效。getError
- 执行验证过程后,如果失败,此方法返回原因。getXMLDocument
- 返回SAML响应文档(如果包含加密的断言,则解密它)。
OneLogin\Saml2\LogoutRequest - LogoutRequest.php
SAML 2注销请求类
LogoutRequest
- 构造注销请求对象。getRequest
- 返回注销请求,已解压、base64编码、未签名。getID
- 返回注销请求的ID。(如果您有对象,可以访问id属性)getNameIdData
- 获取注销请求的NameID数据。getNameId
- 获取注销请求的NameID。getIssuer
- 获取注销请求的发行者。getSessionIndexes
- 获取注销请求中的SessionIndexes。isValid
- 检查收到的注销请求是否有效。getError
- 执行验证过程后,如果失败,此方法返回原因。getXML
- 返回请求或接收到的SP中的XML。
OneLogin\Saml2\LogoutResponse - LogoutResponse.php
SAML 2注销响应类
LogoutResponse
- 构造注销响应对象(从设置中初始化参数,如果提供则加载注销响应)getIssuer
- 获取注销响应的发行者。getStatus
- 获取注销响应的状态。isValid
- 确定SAML注销响应是否有效build
- 生成注销响应对象。getResponse
- 返回注销响应对象。getError
- 执行验证过程后,如果失败,此方法返回原因。getXML
- 返回作为响应部分发送的XML或接收到的SP中的XML。
OneLogin\Saml2\Settings - Settings.php
OneLogin PHP工具箱的配置
Settings
- 初始化设置:设置不同文件夹的路径,从设置文件或提供的数组/对象中加载设置信息checkSettings
- 检查设置信息。getBasePath
- 返回基本路径。getCertPath
- 返回证书路径。getLibPath
- 返回库路径。getExtLibPath
- 返回外部库路径。getSchemasPath
- 返回模式路径。checkSPCerts
- 检查SP的x509证书是否存在且有效。getSPkey
- 返回SP的x509私钥。getSPcert
- 返回SP的x509公钥。getSPcertNew
- 返回SP未来的x509公钥。getIdPData
- 获取IdP数据。getSPData
获取SP数据。getSecurityData
- 获取安全数据。getContacts
- 获取联系数据。getOrganization
- 获取组织数据。getSPMetadata
- 获取SP元数据。XML表示形式。validateMetadata
- 验证XML SP元数据。formatIdPCert
- 格式化IdP证书。formatSPCert
- 格式化SP证书。formatSPCertNew
- 格式化新的SP证书。formatSPKey
- 格式化SP私钥。getErrors
- 返回包含错误信息的数组,当设置正常时数组为空。getLastErrorReason
- 返回最后一个错误的原因。getBaseURL
- 如果设置了,则返回设置的baseurl。setBaseURL
- 设置baseurl值。setStrict
- 激活或禁用严格模式。isStrict
- 返回是否启用了'严格'模式。isDebugActive
- 返回是否启用了调试。
OneLogin\Saml2\Metadata - Metadata.php
一个包含与SP元数据相关功能的类。
builder
- 根据设置生成SP的元数据。signmetadata
- 使用提供的密钥/证书对元数据进行签名。addX509KeyDescriptors
- 将x509描述符(签名/加密)添加到元数据中。
OneLogin\Saml2\Utils - Utils.php
一个包含多个方法的辅助类。
validateXML
- 此函数尝试将XML字符串与指定的模式进行验证。formatCert
- 返回一个x509证书(如果需要,添加标题和页脚)。formatPrivateKey
- 返回一个RSA私钥(如果需要,添加标题和页脚)。redirect
- 执行到提供的url的重定向(或返回目标url)。isHTTPS
- 检查是否是https或http。getSelfHost
- 返回当前主机。getSelfURLhost
- 返回协议 + 当前主机 + 端口(如果与常用端口不同)。getSelfURLNoQuery
- 返回当前主机 + 当前视图的URL。getSelfURL
- 返回当前主机 + 当前视图 + 查询的URL。generateUniqueID
- 生成一个唯一的字符串(例如,用作断言的ID)。parseTime2SAML
- 将UNIX时间戳转换为SAML2时间戳,格式为yyyy-mm-ddThh:mm:ss(.s+)?Z
。parseSAML2Time
- 将格式为yyyy-mm-ddThh:mm:ss(.s+)?Z
的SAML2时间戳转换为UNIX时间戳。忽略子秒部分。parseDuration
- 解释一个相对于给定时间戳的ISO8601持续时间值。getExpireTime
- 比较两个日期并返回最早的一个。query
- 从DOMDocument中提取节点。isSessionStarted
- 检查会话是否已启动。deleteLocalSession
- 删除本地会话。calculateX509Fingerprint
- 计算x509证书的指纹。formatFingerPrint
- 格式化指纹。generateNameId
- 生成nameID
。getStatus
- 从响应中获取状态。decryptElement
- 解密加密的元素。castKey
- 将XMLSecurityKey
转换为正确的算法。addSign
- 将签名密钥和发送者证书添加到元素(消息或断言)中。validateSign
- 验证签名(消息或断言)。
OneLogin\Saml2\IdPMetadataParser - IdPMetadataParser.php
一个包含多个方法以检索和处理IdP元数据的辅助类。
parseRemoteXML
- 从URL获取IdP元数据信息。parseFileXML
- 从文件获取IdP元数据信息。parseXML
- 从XML获取IdP元数据信息。injectIntoSettings
- 将元数据信息注入到php-saml设置数组中。
有关更多信息,请查看源代码;每个方法都有文档,并提供有关其功能和使用方法的详细信息。请确保还检查doc文件夹,其中提供了有关SAML和SAML2的类和方法的HTML文档。
工具包中包含的示例
该工具包包括三个示例应用程序,用于说明如何使用工具包,请查看它。
示例需要在使用之前正确配置SP和IdP。
Demo1
SP设置
Onelogin的PHP工具包允许您以两种方式提供设置信息。
- 使用位于工具包基本文件夹中的
settings.php
文件。 - 使用设置数据数组。
在这个示例中,我们采用第二种方式提供数据,使用名为$settingsInfo
的设置数组。此数组使用包含为模板的settings_example.php
来创建settings.php
设置,并将其存储在demo1/
文件夹中。配置SP部分,然后审查IdP的元数据,并完成IdP信息。
如果您检查index.php
文件的代码,您将看到settings.php
文件被加载,以便使用$settingsInfo
变量来初始化Setting
类。
注意,在这个示例中,位于工具包基础目录中的可能定义的setting.php
文件被忽略,并且使用位于工具包基础目录中的_toolkit_loader.php
来加载库。
IdP设置
一旦配置了SP,SP的元数据就会发布在metadata.php
文件中。根据该信息配置IdP。
工作原理
第一次访问
index.php
视图时,您可以选择登录并返回同一视图或登录并重定向到attrs.php
视图。当您点击
第一个链接中的2.1时,我们访问到
(index.php?sso)
,向IdP发送一个AuthNRequest
,在IdP进行身份验证后,通过用户的客户端将响应发送到SP,具体是Assertion Consumer Service视图:index.php?acs
。注意,将RelayState
参数设置为启动过程的url,即index.php
视图。第二个链接中的2.2,我们访问到
(attrs.php)
,与2.1中描述的过程相同,不同之处在于将RelayState
设置为attrs.php
。SAML响应在ACS(
index.php?acs
)中处理,如果响应无效,则在此停止处理并显示消息。否则,我们将重定向到RelayState视图。a)index.php
或b)attrs.php
。我们登录到应用程序,并显示用户属性。在此阶段,我们可以测试单点登出功能。
单点登出功能可以通过两种方式测试。
5.1 SP启动SLO。在SP上单击“登出”链接,之后向IdP发送一个登出请求,关闭IdP上的会话,并通过客户端回复SP一个登出响应(发送到单点登出服务端点)。SP的SLS端点(
index.php?sls
)处理登出响应,如果有效,则关闭本地应用程序的用户会话。注意,SLO工作流从SP开始并结束。5.2 IdP启动SLO。在这种情况下,操作发生在IdP端,登出过程在IdP处启动,向SP发送一个登出请求(SLS端点,
index.php?sls
)。SP的SLS端点处理登出请求,如果有效,则关闭本地应用程序的用户会话,并向IdP发送一个登出响应(发送到IdP的SLS端点)。IdP接收登出响应,处理它并关闭IdP上的会话。注意,SLO工作流从IdP开始并结束。
请注意,所有SAML请求和响应都由一个文件处理,即index.php
文件,以及如何使用GET
参数来知道必须执行的操作。
演示2
SP设置
Onelogin的PHP工具包允许您以两种方式提供设置信息。
- 使用位于工具包基本文件夹中的
settings.php
文件。 - 使用设置数据数组。
第一个是演示2应用程序的情况。应在工具包的基础目录中定义setting.php
文件和setting_extended.php
文件。审查setting_example.php
和advanced_settings_example.php
,了解如何构建它们。
在这种情况下,作为属性消费服务(Attribute Consume Service)和单点登出服务(Single Logout Service),我们将使用位于端点文件夹中的文件(acs.php
和 sls.php
)。
IdP设置
一旦服务提供者(SP)配置完毕,SP的元数据将发布在 metadata.php
文件中。根据这些信息,配置身份提供者(IdP)。
工作原理
在demo1中,我们看到了所有SAML请求和响应是如何在一个独特的文件 index.php
中处理的。这个demo1使用高级编程。
在demo2中,我们有几个视图:index.php
、sso.php
、slo.php
、consume.php
和 metadata.php
。正如我们所说的,我们将使用工具包中定义的端点(端点文件夹中的 acs.php
和 sls.php
)。这个demo2使用低级编程。
请注意,SSO操作可以在 index.php
或 sso.php
中启动。
发生的SAML工作流程与demo1中定义的工作流程类似,只是改变了目标。
当您第一次访问
index.php
或sso.php
时,会自动向IdP发送一个AuthNRequest
,(因为发送了原始url作为RelayState
)。我们在IdP处进行身份验证,然后向SP发送一个Response
,到端点,在这个例子中是端点文件夹中的acs.php
。SAML响应在ACS中处理,如果
Response
无效,则在此处停止处理并显示消息。否则,我们被重定向到RelayState
视图(sso.php
或index.php
)。sso.php
检测用户是否已登录,并将其重定向到index.php
,因此最终我们将处于index.php
。我们登录到应用程序,并显示用户属性(如果有的话)。在此阶段,我们可以测试单点登出功能。
单点登出功能可以通过两种方式测试。
4.1 由SP启动的SLO。在SP上点击“登出”链接,然后我们被重定向到
slo.php
视图,在那里向IdP发送一个登出请求,关闭IdP处的会话,并回复SP一个登出响应(发送到单点登出服务端点)。在这种情况下,SP的SLS端点处理登出响应,如果有效,关闭本地应用程序的用户会话。请注意,SLO工作流程在SP处开始和结束。4.2 由IdP启动的SLO。在这种情况下,操作在IdP侧进行,登出过程在IdP处启动,向SP发送一个登出请求(端点文件夹的SLS端点
sls.php
)。SP的SLS端点处理登出请求,如果有效,关闭本地应用程序中用户的会话,并发送一个登出响应到IdP(到IdP的SLS端点)。IdP接收登出响应,处理它并关闭IdP的会话。请注意,SLO工作流程在IdP处开始和结束。