onelogin / php-saml
PHP SAML 工具包
Requires
- php: >=7.3
- robrichards/xmlseclibs: ^3.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-master
- 4.2.0
- 4.1.0
- 4.0.1
- 4.0.0.x-dev
- 4.0.0
- 3.7.0
- 3.6.1.x-dev
- 3.6.1
- 3.6.0.x-dev
- 3.6.0
- 3.5.1.x-dev
- 3.5.1
- 3.5.0.x-dev
- 3.5.0
- 3.4.2.x-dev
- 3.4.1.x-dev
- 3.4.1
- 3.4.0.x-dev
- 3.4.0
- 3.3.2.x-dev
- 3.3.1.x-dev
- 3.3.1
- 3.3.0.x-dev
- 3.3.0
- 3.2.1.x-dev
- 3.2.1
- 3.2.0.x-dev
- 3.2.0
- 3.1.1.x-dev
- 3.1.1
- 3.1.0.x-dev
- v3.1.0
- 3.0.0.x-dev
- v3.0.0
- 2.20.0
- 2.19.1
- 2.19.0
- 2.18.1
- 2.18.0
- 2.17.1
- 2.17.0
- 2.16.0
- v2.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-build_with_base_url_path
- dev-3.x-dev
- dev-4.x-dev
- dev-no_value_nameid
- dev-include_83_coverage
- dev-test_openssl
- dev-remove_old_ref
- dev-ci-coveralls
- dev-saml-migration
- dev-whitesource/configure
- dev-migrate-to-gha
- dev-revert-412-master
- dev-custom_scheme_path
- dev-3.0.0-namespaceless
- dev-remove_mcrypt
- dev-composer
- dev-quotespurls
- dev-key_rollover_mngmt
- dev-decrypted-assertion-validation
- dev-url-injection
- dev-nameidformat
- dev-no_uri
This package is not auto-updated.
Last update: 2024-09-19 17:16:04 UTC
README
使用此库将 SAML 支持添加到您的 PHP 软件。
3.X 分支与 PHP 7.0、PHP 7.1、PHP 7.2 兼容,因此如果您使用这些 PHP 版本,请使用它而不是 2.X 或 master 分支
4.X 分支与 PHP >= 7.3 和 PHP 8.X 兼容
警告
版本 2.18.0 引入了 'rejectUnsolicitedResponsesWithInResponseTo' 设置参数,默认禁用,允许使非请求数据的 SAMLResponse 失效。此版本还将拒绝 SAMLResponse,如果 requestId 已提供给验证器,但 SAMLResponse 不包含 InResponseTo 属性。此外,还有一个额外的设置参数 'destinationStrictlyMatches',默认禁用,将强制目标 URL 严格匹配处理 SAMLResponse 的地址。
版本 2.17.1 更新了 xmlseclibs 到 3.0.4 (CVE-2019-3465),但 php-saml 没有直接受到影响,因为它实现了防止利用该漏洞的额外检查。
版本 2.17.0 默认启用严格模式
将 php-saml 更新到 2.15.0,此版本包含针对 XEE 攻击的安全补丁
php-saml 未受 201803-01 影响
将 php-saml 更新到 2.10.4,此版本包含针对 LogoutRequests/LogoutResponses 上的签名验证 的安全补丁
将 php-saml 更新到 2.10.0,此版本包含包含额外验证的安全补丁,这些验证将防止签名包装攻击。 CVE-2016-1000253
php-saml < v2.10.0 存在漏洞,允许签名包装!
安全指南
如果您认为您已发现此工具包中的安全漏洞,请通过邮件向维护者报告:sixto.martin.garcia+security@gmail.com
为什么要在我的软件中添加 SAML 支持?
SAML 是一种基于 XML 的网络浏览器单点登录标准,由 OASIS 安全服务技术委员会定义。该标准自 2002 年以来一直存在,但近年来由于其优势而越来越受欢迎。
- 可用性 - 从门户或内网一键访问、深度链接、消除密码和自动续订会话使用户的生活更加方便。
- 安全性 - 基于强大的数字签名进行身份验证和完整性,SAML 是一种安全单点登录协议,全球最大和最注重安全的公司都依赖该协议。
- 速度 - SAML 很快。只需一次浏览器重定向即可安全地将用户签入应用程序。
- 钓鱼防护 - 如果您没有应用程序的密码,您就不会被欺骗在假登录页面上输入它。
- 对 IT 友好 - SAML 简化了 IT 的工作,因为它集中了身份验证、提供了更大的可见性并使目录集成更加容易。
- 机会 - B2B 云服务提供商应支持 SAML 以促进其产品的集成。
一般描述
SAML PHP 工具包让您在 PHP 应用程序上构建 SP(服务提供商)并将其连接到任何 IdP(身份提供者)。
支持
- SSO 和 SLO(SP-Initiated 和 IdP-Initiated)。
- 断言和nameId加密。
- 断言签名。
- 消息签名:AuthNRequest、LogoutRequest、LogoutResponses。
- 启用断言消费者服务端点。
- 启用单一登出服务端点。
- 发布SP元数据(可签名)。
主要功能
- saml2int - 实现SAML 2.0 Web浏览器单点登录配置文件。
- 无会话 - 忘掉SP和最终应用程序之间的常见冲突,工具包将委托最终应用程序中的会话。
- 易于使用 - 程序员将允许进行高级和低级编程,提供2个易于使用的API。
- 已测试 - 严格测试。
- 受欢迎 - 客户使用它。许多PHP SAML插件使用它。
使用此指南在OneLogin集成PHP工具包:https://developers.onelogin.com/page/saml-toolkit-for-php
安装
依赖项
php >= 5.3.3
和一些核心扩展,如php-xml
、php-date
、php-zlib
。openssl
。安装openssl库。它处理x509证书。mcrypt
。如果您将处理加密数据(nameID
、assertions
),则安装该库及其php驱动程序。curl
。如果您计划使用IdP元数据解析器,则安装该库及其php驱动程序。
由于PHP 5.3已正式停止支持,我们建议您使用较新的PHP版本。
代码
选项1. 从GitHub克隆仓库
git clone git@github.com:onelogin/php-saml.git
选项2. 从GitHub下载
工具包托管在GitHub上。您可以从以下位置下载它:
- 最新版本:https://github.com/onelogin/php-saml/releases/latest
- 主仓库:https://github.com/onelogin/php-saml/tree/master
将库的核心复制到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
安装完成后,您将在vendor/
文件夹中找到一个名为onelogin
的新文件夹,并在其中包含php-saml
。请确保您包含由composer提供的自动加载器。它可以在vendor/autoload.php
中找到。
重要 在此选项中,x509证书必须存储在vendor/onelogin/php-saml/certs
中,设置文件存储在vendor/onelogin/php-saml
中。
当使用composer update
或类似命令更新包时,您的设置可能会被删除。因此,强烈建议您不要使用设置文件,而应直接将设置作为数组传递给构造函数(本文件稍后解释)。如果您不采取此方法,则当使用composer update
或类似命令更新包时,您的设置可能会被删除。
兼容性
此2.0版本有一个新的库。工具包仍然兼容。
您之前用来添加SAML支持的旧代码将正常工作,只需稍作修改。您只需要加载lib/Saml
文件夹中的文件。(注意,compatibility.php
文件负责此操作)。
旧-demo文件夹包含一个使用旧版工具包(v.1)的旧应用的代码。请查看。
有时旧代码中类的名称可能略有不同,如果这是您的情况,则必须将它们更改为OneLogin_Saml_Settings
、OneLogin_Saml_Response
、OneLogin_Saml_AuthRequest
或OneLogin_Saml_Metadata
。
我们建议您将旧代码迁移到新版本,以便使用新库Saml2带来的新功能。
命名空间
如果您正在使用包含命名空间的框架(如Symfony)的库,请记住,对类的调用必须通过在开头添加反斜杠(\
)来完成,例如,要使用静态方法getSelfURLNoQuery,请使用
\OneLogin_Saml2_Utils::getSelfURLNoQuery()
安全警告
在生产环境中,必须将strict
参数设置为"true"
,并且必须在security
下的signatureAlgorithm
和digestAlgorithm
中设置除SHA1之外的内容(参见https://shattered.io/)。否则,您的环境不安全,容易受到攻击。
在生产环境中,我们还强烈建议在设置中注册IdP证书,而不是使用指纹方法。指纹是一个散列值,因此最终容易受到碰撞攻击,这可能导致签名验证绕过。其他SAML工具包已弃用该机制,我们保留它以保持兼容性,并用于测试环境。
避免Open Redirect攻击
某些实现使用RelayState参数作为控制SSO和SLO成功时流程的一种方式。所以基本上用户将被重定向到RelayState的值。
如果您正在使用HTTP-Redirect绑定上的签名验证,则RelayState值的完整性将得到保证,否则,在HTTP-POST绑定中,您不能相信RelayState的值,因此在进行验证之前,您需要验证其值属于受信任和预期的URL。
有关Open Redirect的更多信息,请参阅CWE-601。
避免Reply攻击
Reply攻击基本上是尝试重用截获的有效SAML消息以冒充SAML操作(SSO或SLO)。
SAML消息有有限的有效期(NotBefore、NotOnOrAfter),这使得这种攻击更加困难,但它们仍然是可能的。
为了避免它们,SP可以保留一个已验证并处理过的SAML消息或Assertion ID的列表。这些值只需存储SAML消息生命周期的时长,因此我们不需要存储所有处理过的消息/断言ID,只需存储最新的即可。
OneLogin_Saml2_Auth类包含getLastRequestID、getLastMessageId和getLastAssertionId方法来检索ID
检查当前消息/断言的ID是否不在已处理的列表中,这将防止Reply攻击。
入门
了解工具包
新的OneLogin SAML工具包包含不同的文件夹(certs
、endpoints
、extlib
、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证书,或者使用一个新的x509证书:metadata.crt
和 metadata.key
。
如果你正在进行密钥滚动过程,并且想在服务提供者元数据上发布该x509证书,请使用 sp_new.crt
。
extlib/
此文件夹包含工具包使用的第三方库。目前仅使用 xmlseclibs
(作者Robert Richards,BSD许可),该库用于处理xml元素的签名和加密。
lib/
此文件夹包含工具包的核心,即库
Saml
文件夹包含工具包v.1的修改版本,允许旧代码继续工作。(此库提供以保持向后兼容)。Saml2
文件夹包含后面章节中描述的新版本类和方法。
doc/
此文件夹包含工具包的API文档。
endpoints/
工具包有三个端点
metadata.php
- SP的元数据在此处发布。acs.php
- 断言消费者服务。处理SAML响应。sls.php
- 单一登出服务。处理登出请求和登出响应。
您可以使用工具包提供的文件,或者在添加SAML支持到您的应用程序时创建自己的端点文件。请注意,这些端点文件使用工具包基础文件夹的设置文件。
locale/
本地化文件夹包含一些翻译:en_US
和 es_ES
作为概念证明。目前没有翻译,但我们将最终本地化消息并支持多种语言。
其他重要文件
settings_example.php
- 创建包含工具包基本配置信息的settings.php
文件的模板。advanced_settings_example.php
- 创建包含与安全、联系人信息和与SP关联的组织相关的额外配置信息的advanced_settings.php
文件的模板。_toolkit_loader.php
- 此文件加载工具包库(SAML2库)。compatibility
- 导入此文件以使您的旧代码与新工具包兼容(加载SAML库)。
杂项
tests/
- 包含工具包的单元测试。demo1/
- 包含一个带有SAML支持的简单PHP应用程序示例。阅读其中的Readme.txt
以获取更多信息。demo2/
- 包含另一个示例。demo-old/
- 包含一个使用旧版工具包代码的示例,以展示向后兼容性。
工作原理
设置
首先,我们需要配置工具包。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. SAML 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. SAML 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. SAML 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 the SP will send the SLO Response (ResponseLocation) // if not set, url for the SLO Request will be used 'responseUrl' => '', // SAML protocol binding to be used when returning the <Response> // message. SAML 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' => false, // 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, the toolkit will not raised an error when the Statement Element // contain atribute elements with name duplicated 'allowRepeatAttributeName' => 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 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);
如何加载库
为了使用工具包库,您需要导入位于工具包基本目录中的_toolkit_loader.php
文件。您可以以这种方式加载此文件
<?php define("TOOLKIT_PATH", '/var/www/php-saml/'); require_once(TOOLKIT_PATH . '_toolkit_loader.php');
在此行之后,我们将能够使用工具包的类(及其方法)(因为加载了外部和Saml2库文件)。
如果您为PHP-SAML工具包的版本1编写了SAML应用的代码,您将需要加载compatibility.php
文件,该文件加载SAML库文件,除了_toolkit_loader.php
。
该SAML库使用最新版本工具包的新类和方法,但保留了旧类、方法和旧流程,以完成相同的事情。
我们强烈建议将旧代码迁移到使用新工具包的新API,因为有很多新功能是旧代码无法处理的。
启动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
AuthNRequest
将根据advanced_settings.php
中的安全信息('authnRequestsSigned'
)进行签名或未签名。
然后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字符串),则为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视图。工具包在端点目录中提供了这些视图的示例。
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']) { // To avoid 'Open Redirect' attacks, before execute the // redirection confirm the value of $_POST['RelayState'] is a // trusted URL. $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响应并检查是否有错误。它还验证用户是否已认证并将用户数据存储在会话中。
此时有两种可能的方案
-
如果没有提供
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
- 用于标识用户会话的会话索引。$stay
- 如果我们想停留(返回URL字符串),则返回False以重定向。$nameIdFormat
- 将在登出请求中设置NameID格式。$nameIdNameQualifier
- 将在登出请求中设置NameID名称限定符。$nameIdSPNameQualifier
- 将在登出请求中设置NameID SP 名称限定符。
根据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;
$paramters = 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, $paramters, $nameId, $sessionIndex, false, $nameIdFormat, $nameIdNameQualifier, $nameIdSPNameQualifier);
如果需要匹配未来的注销响应ID和要发送的注销请求ID,则必须提取并存储该注销请求ID。
$sloBuiltUrl = $auth->logout(null, $paramters, $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 external libs 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']) { // To avoid 'Open Redirect' attacks, before execute the // redirection confirm the value of $_POST['RelayState'] is a // trusted URL. $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>'; }
使用Composer启动SSO请求并处理响应的示例(是acs目标)
通过composer安装包
composer require onelogin/php-saml
创建一个index.php
<?php require('vendor/autoload.php'); session_start(); $needsAuth = empty($_SESSION['samlUserdata']); if ($needsAuth) { // put SAML settings into an array to avoid placing files in the // composer vendor/ directories $samlsettings = array(/*...config goes here...*/); $auth = new \OneLogin\Saml2\Auth($samlsettings); if (!empty($_REQUEST['SAMLResponse']) && !empty($_REQUEST['RelayState'])) { $auth->processResponse(null); $errors = $auth->getErrors(); if (empty($errors)) { // user has authenticated successfully $needsAuth = false; $_SESSION['samlUserdata'] = $auth->getAttributes(); } } if ($needsAuth) { $auth->login(); } } // rest of your app goes here
URL猜测方法
php-saml工具包在OneLogin_Saml2_Utils中使用多种方法来猜测处理SAML消息的URL。
getSelfHost
返回当前主机。getSelfPort
返回请求使用的端口号。isHTTPS
检查协议是否为https或http。getSelfURLhost
返回协议 + 当前主机 + 端口(如果不同于常见端口)。getSelfURL
返回当前主机 + 当前视图 + 查询。getSelfURLNoQuery
返回当前主机 + 当前视图的URL。getSelfRoutedURLNoQuery
返回当前主机 + 当前视图的路由URL。
getSelfURLNoQuery和getSelfRoutedURLNoQuery用于计算当前URL,以便验证SAML元素,如Destination或Recipient。
当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响应的Destination属性可能会失败。
您可以通过配置服务器使其了解代理并返回请求的原始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。
主要类和方法
以下描述了可以调用的主要类和方法。
旧版SAML库
让我们开始描述SAML库的类和方法,这是一个旧版v.1工具包的演变,用于保持向后兼容性。其中大多数使用新的SAML2库的类和方法。
OneLogin_Saml_AuthRequest - AuthRequest.php
具有受保护的属性$auth
,一个OneLogin_Saml2_Auth
对象。
OneLogin_Saml_AuthRequest
- 构造OneLogin_Saml2_Auth
,初始化SP SAML实例。getRedirectUrl($returnTo)
- 获取包含压缩后的AuthRequest消息的SSO URL。
OneLogin_Saml_Response - Response.php
OneLogin_Saml_Response
- 处理SAML响应的构造函数,内部初始化SP SAML实例和OneLogin_Saml2_Response
。get_saml_attributes
- 获取一个包含已登录用户数据的数组。
OneLogin_Saml_Settings - Settings.php
一个简单的类,用于构建工具包v1.0中使用的设置对象。
OneLogin_Saml_Metadata - Metadata.php
OneLogin_Saml_Metadata
- 构造函数,根据SP的设置构建元数据XML信息。getXml
- 包含SP元数据信息的XML。
OneLogin_Saml_XmlSec - XmlSec.php
一个辅助类,包含验证SAML响应的方法:validateNumAssertions
、validateTimestamps
、isValid
(它使用前面两个方法并验证SAML响应的签名)。
Saml2库
现在让我们描述SAML2库的类和方法。
OneLogin_Saml2_Auth - Auth.php
PHP工具包的主类
OneLogin_Saml2_Auth
- 初始化SP SAML实例login
- 启动SSO流程。logout
- 启动SLO流程。processResponse
- 处理由IdP发送的SAML响应。processSLO
- 处理由IdP发送的SAML登出响应/登出请求。redirectTo
- 将用户重定向到参数中指定的URL或我们定义的SSO请求的URL。isAuthenticated
- 检查用户是否已认证。getAttributes
- 返回SAML属性的集合。getAttribute
- 返回请求的SAML属性。getNameId
- 返回nameID。getNameIdFormat
- 获取来自IdP的SAML响应提供的NameID格式。getNameIdNameQualifier
- 获取来自SAML响应字符串的NameID NameQualifier。getNameIdSPNameQualifier
- 获取来自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 认证请求类
OneLogin_Saml2_AuthnRequest
- 构造AuthnRequest
对象。getRequest
- 返回压缩、base64编码、未签名的AuthnRequest
。getId
- 返回AuthNRequest
ID。getXML
- 返回请求中将发送的XML。
OneLogin_Saml2_Response - Response.php
SAML 2 认证响应类
OneLogin_Saml2_Response
- 构造SAML响应对象。isValid
- 使用证书确定SAML响应是否有效。checkStatus
- 检查状态是否成功。getAudiences
- 获取受众。getIssuers
- 获取发行者(从响应和断言中获取)getNameIdData
- 获取SAML响应从IdP提供的NameID数据。getNameId
- 获取SAML响应从IdP提供的NameID。getNameIdFormat
- 获取来自IdP的SAML响应提供的NameID格式。getNameIdNameQualifier
- 获取来自SAML响应字符串的NameID NameQualifier。getNameIdSPNameQualifier
- 获取来自SAML响应字符串的NameID SP NameQualifier。getSessionNotOnOrAfter
- 从AuthnStatement获取SessionNotOnOrAfter。getSessionIndex
- 获取AuthnStatement中的SessionIndex。getAttributes
- 从AttributeStatement元素获取属性。validateNumAssertions
- 验证文档只包含单个断言(加密或不加密)。validateTimestamps
- 验证根据条件元素文档是否仍然有效。getError
- 执行验证过程后,如果失败,此方法返回原因getXMLDocument
- 返回SAML响应文档(如果包含加密的断言,则解密它)
OneLogin_Saml2_LogoutRequest - LogoutRequest.php
SAML 2 注销请求类
OneLogin_Saml2_LogoutRequest
- 构造注销请求对象。getRequest
- 返回注销请求的压缩、base64编码、未签名的。getID
- 返回注销请求的ID。 (如果您有对象,您可以访问id属性)getNameIdData
- 获取注销请求的NameID数据。getNameId
- 获取注销请求的NameID。getIssuer
- 获取注销请求的发行者。getSessionIndexes
- 获取注销请求的SessionIndexes。isValid
- 检查接收到的注销请求是否有效。getError
- 执行验证过程后,如果失败,此方法返回原因getXML
- 返回请求中将发送的XML或SP接收到的XML。
OneLogin_Saml2_LogoutResponse - LogoutResponse.php
SAML 2 注销响应类
OneLogin_Saml2_LogoutResponse
- 构造一个注销响应对象(从设置中初始化参数,如果提供则加载注销响应)getIssuer
- 获取注销响应的发行者。getStatus
- 获取注销响应的状态。isValid
- 确定SAML注销响应是否有效build
- 生成注销响应对象。getResponse
- 返回注销响应对象。getError
- 执行验证过程后,如果失败,此方法返回原因。getXML
- 返回作为响应的一部分将发送的XML或SP接收到的XML。
OneLogin_Saml2_Settings - Settings.php
PHP工具包的配置
OneLogin_Saml2_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设置数组中。
该类在以parseRemoteXML等方法引入URL来检索远程XML的方式上不进行任何验证。通常,处理服务提供者的管理员会设置属于受信任第三方IdP的URL。但存在其他场景,例如SAAS应用程序,其中应用程序管理员将任务委托给其他管理员。在这种情况下,应采取额外的保护措施,以验证此类URL输入并避免如SSRF之类的攻击。
有关更多信息,请参阅源代码;每个方法都有文档,并提供了关于它做什么以及如何使用的详细信息。请确保也检查doc文件夹,其中提供了关于SAML和SAML2的类和方法的HTML文档。
工具包中包含的示例
该工具包包含三个示例应用程序,用于教授如何使用该工具包,请查看它。
示例在测试之前需要确保SP和IdP配置良好。
示例1
SP设置
PHP Toolkit允许您以两种方式提供设置信息
- 使用位于工具包基础文件夹中的
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与我们描述的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设置
PHP Toolkit允许您以两种方式提供设置信息
- 使用位于工具包基础文件夹中的
settings.php
文件。 - 使用包含设置数据的数组。
首先,是demo2应用程序的情况。setting.php
文件和setting_extended.php
文件应在工具包的基础文件夹中定义。查看setting_example.php
和advanced_settings_example.php
以了解如何构建它们。
在这种情况下,我们将使用位于端点文件夹中的文件(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发送一个响应,到ACS端点,在这种情况下是端点文件夹中的acs.php
。 -
SAML响应在ACS中处理,如果响应无效,则在此处停止处理并显示消息。否则,我们将重定向到
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开始并结束。
旧演示
SP设置
这个演示使用工具包版本1的旧样式。必须向AuthRequest
构造函数提供一个OneLogin_Saml_Settings
类的对象。
您可以在demo-old文件夹中找到名为example_settings.php
的文件,该文件可以用作您的settings.php
文件的模板。
在该模板中,SAML设置分为两部分,应用程序特定的(const_assertion_consumer_service_url
、const_issuer
、const_name_identifier_format
)和用户/账户特定的idp_sso_target_url
、x509certificate
)。您需要在此处添加自己的代码来识别用户或用户来源(例如通过subdomain
、ip_address
等)。
IdP设置
一旦配置了SP,SP的元数据将发布在metadata.php
文件中。之后,根据该信息配置IdP。
工作原理
在metadata.php
视图中发布的是SP的元数据。
如果应用程序需要启动SAML对话,则index.php
文件充当启动器。这被称为服务提供商启动的SAML。服务提供商创建一个SAML身份验证请求并将其发送到身份提供者(IdP)。
consume.php
是ACS端点。接收SAML断言。在响应验证之后,用户数据和nameID将可用,使用getNameId()
或getAttributes()
我们可以获取它们。
由于php工具包的1.0版本不支持SLO,因此在本demo-old中不展示如何处理SLO。