krixon / multi-factor-auth
PHP7的多种因素认证库
Requires
- php: >=7.2
Requires (Dev)
- ext-curl: >=7.2
- php-coveralls/php-coveralls: ^2.1
- php-mock/php-mock-phpunit: ^2.3
- phpunit/phpunit: ^8.1.0
This package is auto-updated.
Last update: 2024-09-19 22:02:45 UTC
README
一个用于生成和验证在多种因素认证系统中使用的代码的库。
特性
此库实现了以下RFC
它已与以下多种因素认证工具进行了测试
- Google Authenticator (TOTP + HOTP)
- Authy (TOTP + HOTP)
先决条件
- PHP 7.1+
安装
通过Composer安装
要使用Composer安装此库,请运行以下命令
$ composer require krixon/multi-factor-auth
您可以在Packagist上看到此库。
从源代码安装
# HTTP $ git clone https://github.com/krixon/multi-factor-auth.git # SSH $ git clone git@github.com:krixon/multi-factor-auth.git
快速开始
假设您有一个服务器端应用程序,您想使用多种因素认证来保护它。
涉及三个主要步骤
- 生成一个在服务器和用户之间共享的秘密。
- 使用共享秘密配置客户端应用程序(如Google Authenticator)。
- 当用户需要认证时,验证客户端应用程序生成的代码。
此库使这些步骤变得简单。
快速开始的方法是创建一个新的MultiFactorAuth
类的实例。这个构造函数接受多个参数,但提供了一个静态工厂,它使用合理的默认值创建实例。您需要提供的只是“发行者”字符串。这只是一个标签,用于标识管理用户账户的提供者或服务 - 即您的应用程序。
<?php use Krixon\MultiFactorAuth\MultiFactorAuth; $mfa = MultiFactorAuth::default('Example Issuer');
接下来,您需要生成共享秘密。默认情况下,下面的代码将生成一个160位的base32编码字符串
$secret = $mfa->generateSecret();
为了使用户能够配置他们的客户端应用程序,他们需要输入刚才生成的秘密。通常,用户的客户端应用程序将运行在他们的手机上。手动输入160位的秘密当然是可以的,但我们可以通过为用户提供一个条形码来扫描来简化这个过程。此条形码包含配置客户端所需的所有信息。
在生成条形码时,您还必须提供一个账户标识符。这可以是任何字符串,使用户能够在他们的客户端应用程序中区分多个账户。一个好的值是用户的电子邮件地址。
$barcode = $mfa->generateTimeBasedBarcode($secret, 'jane.doe@example.com');
generateTimeBasedBarcode()
方法返回一个Barcode
实例。这可以用来最终渲染图像,例如在网页上
<img src="<?= $barcode->dataUri() ?>">
当用户扫描条形码后,应该提示他们输入一个可以验证的代码,以确定配置过程成功。
$verified = $mfa->verifyTimeBasedCode($code, $secret);
如果代码验证成功,则可以在服务器上安全地持久保存秘密,例如在数据库中。
从现在开始,当用户认证时,应该提示他们输入一个代码,以及他们的其他凭证,如用户名和密码。此代码应使用存储的共享秘密进行验证,如果验证失败,则拒绝认证。
生成备份代码
如果用户丢失了设备或无法生成代码,您可以允许他们通过预先生成的备份代码进行登录。基于事件(HOTP)的代码非常适合此用途。
以下示例生成了10个备份代码,用户可以将其写下或以其他方式存储。
use Krixon\MultiFactorAuth\Codec\Base32Codec; use Krixon\MultiFactorAuth\MultiFactorAuth; $mfa = MultiFactorAuth::default('Test Issuer'); // Secrets are expected to be in base32 by default for compatibility with Google Authenticator and similar apps. // It is possible to use any encoding (including none). See below for more information. $secret = (new Base32Codec())->encode('12345678901234567890'); // Retrieve the real counter from the DB or wherever it is stored. $counter = 42; // $codes is an array of 10 strings, each 6 digits long. $codes = $mfa->generateBackupCodes($secret, $counter, 10, 6); foreach ($codes as $code) { // Do something with the backup code. // Generally you would salt and hash the code and store it in a database. These codes would be checked // against the one entered by the user (in addition to checking the current time or event-based code). echo "$code\n"; }
生成密钥
默认情况下,密钥是通过使用 RandomBytesSecretGenerator
生成的。这使用PHP的 random_bytes
函数生成加密安全的密钥。如果需要不同的方法,只需实现 SecretGenerator
接口。
RandomBytesSecretGenerator
接收一个 Codec
实例,该实例确定如何对生成的密钥进行编码。为了与Google Authenticator和类似的应用程序实现最大兼容性,密钥应使用base32编码,因此如果没有指定其他编码,则使用 Base32Codec
。
要生成密钥,可以直接使用 SecretGenerator
,或者使用 MultiFactorAuth
门面。
$generator = new RandomBytesSecretGenerator(); // Generates a base32-encoded, 20 byte random secret. $secret = $generator->generateSecret(); // Generates a base32-encoded, 30 byte random secret. $secret = $generator->generateSecret(30); // Generates a raw binary, 20 byte random secret. $generator = new RandomBytesSecretGenerator(new PassThroughCodec()); $secret = $generator->generateSecret(30); // Generates a base32-encoded, 20 byte random secret. $mfa = MultiFactorAuth::default('Test Issuer'); $secret = $mfa->generateSecret();
沙盒
在 examples
目录中有一个简单的沙盒脚本,可用于生成密钥和条形码,以及验证客户端应用程序生成的代码。
可以使用PHP内置的web服务器运行沙盒。请确保指定正确的 examples
目录路径。
php -S localhost:8080 -t /path/to/krixon/multi-factor-auth/examples
现在可以访问 https://:8080/sandbox.php 使用沙盒。
待办事项
- 更多自动化测试。
- 扩展文档。
- 验证对RFC6287 - OCRA: OATH Challenge-Response Algorithm 的支持。