dartmoon / spid-php-lib
SPID认证的PHP包
Requires
- php: ^7.4 || ^8.0
- robrichards/xmlseclibs: ^3.0
Requires (Dev)
- phpunit/phpunit: ^9.5
- squizlabs/php_codesniffer: ^3.3
README
当前版本:v0.35
spid-php-lib
SPID认证的PHP包。
此PHP包旨在实现SPID 服务提供商。 SPID 是意大利的数字身份系统,允许公民使用一组凭据访问所有公共服务。此包通过仅暴露实现Web应用中SPID认证所需子集的SAML协议,提供了一层抽象。
PHP的替代方案
基于 spid-php-lib 的特定框架库和示例
- https://github.com/italia/spid-symfony-bundle
- https://github.com/simevo/spid-symfony3-example
- https://github.com/simevo/spid-wordpress
其他语言的替代方案
目录
仓库布局
入门
在以下环境中测试过:amd64 Debian 9.5 (stretch,当前稳定版) 与 PHP 7.0。
支持PHP 7.0,7.1和7.2。
先决条件
sudo apt install composer make openssl php-curl php-zip php-xml
配置和安装
注意:在测试期间,请使用测试身份提供者 spid-testenv2。
-
使用composer安装
composer require italia/spid-php-lib
-
(可选) 手动为您的服务提供商(SP)生成密钥和证书文件。
示例:
openssl req -x509 -nodes -sha256 -days 365 -newkey rsa:2048 -subj "/C=IT/ST=Italy/L=Milan/O=myservice/CN=localhost" -keyout sp.key -out sp.crt
此步骤可以跳过:如果声明了可选的
sp_key_cert_values
键,则库会自动处理此步骤。有关详细信息,请参阅使用方法部分的示例。 -
下载身份提供者(IdP)元数据文件,并将它们放置在项目目录中,例如
idp_metadata
。提供了一个便捷工具用于下载生产 IdP 的元数据:vendor/italia/spid-php-lib/bin/download_idp_metadata.php,示例用法mkdir idp_metadata php vendor/italia/spid-php-lib/bin/download_idp_metadata.php ./idp_metadata
测试环境:如果您正在使用 spid-testenv2,请手动下载 IdP 元数据并将其放置在您的
idp_metadata
文件夹中 -
使您的 SP 识别给 IdP:对于生产环境,请遵循 https://www.spid.gov.it/come-diventare-fornitore-di-servizi-pubblici-e-privati-con-spid 上的指南
测试环境:简单地将您的服务提供者(SP)元数据下载到 测试环境 的相应文件夹。在更改 SP 元数据后,必须重新启动测试环境。
用法
此包提供的所有类都位于 Italia\Spid
命名空间中。更详细的文档可在 SAMLInterface.php 文件中找到。
使用 composer 生成的自动加载器加载它们
require_once(__DIR__ . "/vendor/autoload.php");
主要类是 Italia\Spid\Sp
(服务提供者)。
按照以下指南生成设置数组
$settings = array( 'sp_entityid' => SP_BASE_URL, // preferred: https protocol, no trailing slash, example: https://sp.example.com/ 'sp_key_file' => '/path/to/sp.key', 'sp_cert_file' => '/path/to/sp.crt', 'sp_comparison' => 'exact', // one of: "exact", "minimum", "better" or "maximum" 'sp_assertionconsumerservice' => [ // order is important ! the 0-base index in this array will be used as ID in the calls SP_BASE_URL . '/acs', ... ], 'sp_singlelogoutservice' => [ // order is important ! the 0-base index in this array will be used as ID in the calls [SP_BASE_URL . '/slo', 'POST'], [SP_BASE_URL . '/slo', 'REDIRECT'] ... ], 'sp_org_name' => 'your organization full name', 'sp_org_display_name' => 'your organization display name', 'sp_key_cert_values' => [ // Optional: remove this if you want to generate .key & .crt files manually 'countryName' => 'Your Country', 'stateOrProvinceName' => 'Your Province or State', 'localityName' => 'Locality', 'commonName' => 'Name', 'emailAddress' => 'your@email.com', ] 'idp_metadata_folder' => '/path/to/idp_metadata/', 'sp_attributeconsumingservice' => [ // order is important ! the 0-base index in this array will be used as ID in the calls ["fiscalNumber"], ["name", "familyName", "fiscalNumber", "email", "spidCode"], ... ], // Time in seconds of skew that is acceptable between client and server when checking OnBefore and NotOnOrAfter // assertion condition validity timestamps, and IssueInstant response / assertion timestamps. Optional. // Default is 0. Acceptable range: 0-300 (inclusive) 'accepted_clock_skew_seconds' => 100 );
然后初始化主 Sp 类
$sp = new Italia\Spid\Sp($settings);
不想让库为您生成 .key 和 .crt 文件?那么请从
settings
数组中删除sp_key_cert_values
键,或声明
// $autoconfiguration skips .key/.crt generation if set to false $sp = new Italia\Spid\Sp($settings, null, $autoconfiguration = false);
执行登录
// shortname of IdP, same as the name of corresponding IdP metadata file, without .xml $idpName = 'testenv'; // index of assertion consumer service as per the SP metadata (sp_assertionconsumerservice in settings array) $assertId = 0; // index of attribute consuming service as per the SP metadata (sp_attributeconsumingservice in settings array) $attrId = 1; // Generate the login URL and redirect to the IdP login page $sp->login($idpName, $assertId, $attrId);
通过调用以下内容完成登录操作
$sp->isAuthenticated();
在断言消费者服务 URL 上。
然后调用
$userAttributes = $sp->getAttributes();
以接收请求的用户属性数组。
执行注销
调用
// index of single logout service as per the SP metadata (sp_singlelogoutservice in settings array) $sloId = 0; $sp->logout($sloId);
此方法将重定向到 IdP 单一注销页面,或者如果您未登录,则返回 false。
完整 API
方法 | 描述 |
---|---|
__contruct($settings, $protocol = null, $autoconfigure = true) | $settings 应基于 用法 部分中提供的示例。 $protocol 代表用于登录的协议。目前仅支持 SAML ,可以通过将 $protocol = 'saml' 或默认值 $protocol = null 来选择。 $autoconfigure 通知构造函数是否应检查 $settings 数组中指定的位置是否存在 .key 和 .crt 文件,并在找不到时生成它们。如果希望手动生成这些文件,则将其设置为 false 。 |
loadIdpFromFile(string $filename) | 通过解析在 $filename 中提供的 XML 加载 Idp 对象 |
getIdpList() : array | 从在设置中提供的 idp_metadata_folder 加载所有 Idp 对象 |
getIdp(string $filename) | loadIdpFromFile 的别名 |
getSPMetadata() : string | 返回 SP 元数据作为字符串 |
login(string $idpFilename, int $assertID, int $attrID, $level = 1, string $redirectTo = null, $shouldRedirect = true) | 使用REDIRECT绑定进行登录。使用$idpFilename 在IdP中选取登录方式,通过指定XML文件名(不包含扩展名)来标识你的idp_metadata_folder 中的XML文件。$assertID 和$attrID 分别表示在设置中提供的sp_assertionconsumerservice 和sp_attributeconsumingservice 的数组索引。可选参数:$level 用于SPID认证级别(1、2或3),$redirectTo 用于指定登录后重定向的URL,$shouldRedirect 用于指定登录函数是否应自动重定向到IdP或返回登录URL作为字符串 |
loginPost(string $idpName, int $ass, int $attr, $level = 1, string $redirectTo = null, $shouldRedirect = true) | 类似于登录,但使用POST绑定 |
logout(int $slo, string $redirectTo = null, $shouldRedirect = true) | 使用REDIRECT绑定进行注销。$slo 表示在设置中提供的sp_singlelogoutservice 的数组索引。可选参数:$redirectTo 用于指定登录后重定向的URL,$shouldRedirect 用于指定登录函数是否应自动重定向到IdP或返回登录URL作为字符串 |
logoutPost(int $slo, string $redirectTo = null, $shouldRedirect = true) | 类似于注销,但使用POST绑定 |
isAuthenticated() : bool | 检查用户是否已认证。此方法必须在登录和注销后调用以完成操作。 |
getAttributes() : array | 如果在登录期间请求了属性消耗服务,此方法将以数组格式返回它们 |
示例
在存储库的example/
目录中提供了一个基本的演示应用程序。
在packagist的生产版本中不提供/example和/test文件夹,请记住需要dev-develop
版本或直接克隆此存储库(建议)
要尝试它
-
使用以下命令生成测试证书和密钥对
openssl req -x509 -nodes -sha256 -days 365 -newkey rsa:2048 -subj "/C=IT/ST=Italy/L=Milan/O=myservice/CN=localhost" -keyout sp.key -out sp.crt
-
通过在
example/index.php
文件中更改$base
变量来适配SP的主机名;你将测试的浏览器必须能够解析FQDN(默认为https://sp.example.com
)。强烈建议使用HTTPS。 -
配置和安装测试IdP spid-testenv2
-
使用你喜欢的Web服务器提供
example
目录 -
访问https://sp.example.com/metadata以获取SP元数据,然后将其复制到IdP并使用IdP注册SP
-
访问https://idp.example.com/metadata以获取IdP元数据,然后将其保存为
example/idp_metadata/testenv.xml
以使用SP注册IdP -
访问:https://sp.example.com并点击
login
。
演示应用程序
在https://github.com/simevo/spid-php-lib-example中提供了一个基于Docker的演示应用程序。
特性
- 提供了一个不依赖于外部SAML包的
瘦实现
无路由限制
,可以集成到任何Web框架/内容管理系统- 使用
会话
来存储认证结果和接收到的属性 - 目前不支持属性权威(AA)
![]() 符合SPID规定(针对服务提供商) |
|
---|---|
元数据 | |
解析IdP XML元数据(1.2.2.4) | ✓ |
支持IdP XML元数据中的多个签名证书(1.2.2.4) | |
解析AA XML元数据(2.2.4) | |
生成SP XML元数据(1.3.2) | ✓ |
生成AuthnRequest(1.2.2.1) | |
生成AuthnRequest XML | ✓ |
HTTP-Redirect绑定 | ✓ |
HTTP-POST绑定 | ✓ |
AssertionConsumerServiceURL 自定义 |
库使用AssertionConsumerServiceIndex 自定义,这是首选的 |
AssertionConsumerServiceIndex 自定义 |
✓ |
AttributeConsumingServiceIndex 自定义 |
✓ |
AuthnContextClassRef (SPID级别)自定义 |
✓ |
RequestedAuthnContext/@Comparison 自定义 |
✓ |
RelayState 自定义(1.2.2) |
✓ |
解析Response/Assertion | |
验证Signature 值(如有) |
✓ |
验证Signature 证书(如有)与IdP/AA元数据 |
✓ |
验证Assertion/Signature 值 |
✓ |
验证Assertion/Signature 证书与IdP/AA元数据 |
✓ |
验证SubjectConfirmationData/@Recipient |
✓ |
验证SubjectConfirmationData/@NotOnOrAfter |
✓ |
验证SubjectConfirmationData/@InResponseTo |
✓ |
验证Issuer |
✓ |
验证Assertion/Issuer |
✓ |
验证Destination |
✓ |
验证Conditions/@NotBefore |
✓ |
验证Conditions/@NotOnOrAfter |
✓ |
验证Audience |
✓ |
解析没有Assertion 的Response(认证/查询失败) |
✓ |
解析失败StatusCode (请求者/响应者) |
✓ |
为SSO解析Response/Assertion(1.2.1,1.2.2.2,1.3.1) | |
解析NameID |
✓ |
解析AuthnContextClassRef (SPID级别) |
✓ |
解析属性 | ✓ |
为属性查询解析Response/Assertion(2.2.2.2,2.3.1) | |
解析属性 | |
生成LogoutRequest(用于SP发起的注销) | |
生成LogoutRequest XML | ✓ |
HTTP-Redirect绑定 | ✓ |
HTTP-POST绑定 | ✓ |
解析LogoutResponse(用于SP发起的注销) | |
解析LogoutResponse XML | ✓ |
验证Response/Signature 值(如有) |
✓ |
验证Response/Signature 证书(如有)与IdP元数据 |
✓ |
验证Issuer |
✓ |
验证Destination |
✓ |
检测部分注销 | 挂起,请参阅:#46 |
解析LogoutRequest(用于第三方发起的注销) | |
解析LogoutRequest XML | ✓ |
验证Response/Signature 值(如有) |
✓ |
验证Response/Signature 证书(如有)与IdP元数据 |
✓ |
验证Issuer |
✓ |
验证Destination |
✓ |
解析NameID |
✓ |
生成LogoutResponse(用于第三方发起的注销) | |
生成LogoutResponse XML | ✓ |
HTTP-Redirect绑定 | ✓ |
HTTP-POST绑定 | ✓ |
部分注销自定义 | 挂起,请参阅:#46 |
生成AttributeQuery(2.2.2.1) | |
生成AttributeQuery XML | |
SOAP绑定(客户端) |
更多功能
- 生成SPID按钮标记
故障排除
建议安装浏览器插件以跟踪SAML消息
-
Firefox
-
Chrome/Chromium
此外,您可以使用onelogin提供的SAML开发者工具来了解发生了什么
测试
要测试和检查此包,您必须将其置于根目录,然后按照提供的说明进行操作。
假设您已使用composer按照安装说明进行操作,只需执行以下操作
cd vendor/italia/spid-php-lib
单元测试
使用composer安装先决条件,为SP生成密钥和证书,并下载所有当前生产IdP的元数据
composer install bin/download_idp_metadata.php example/idp_metadata
然后使用PHPunit启动单元测试
./vendor/bin/phpunit --stderr --testdox tests
检查
此项目符合PSR-2:编码风格指南。
确保您处于包目录中,然后使用以下命令检查代码
./vendor/bin/phpcs --standard=PSR2 xxx.php
贡献
对于您的贡献,请使用git-flow 工作流程。
相关链接
- 开发者意大利上的SPID页面
作者
洛伦佐·卡塔内奥和帕奥洛·格雷皮,simevo s.r.l.
许可证
版权所有 (c) 2018-2020,开发者意大利
许可证:BSD 3-Clause,请参阅LICENSE文件。