kynx / mezzio-authentication-apikey
在 Mezzio 应用程序中使用 API 密钥验证用户
Requires
- php: ~8.2
- kynx/api-key-generator: ^2.0
- mezzio/mezzio-authentication: ^1.8
- psr/container: ^1.0 || ^2.0
- psr/http-factory: ^1.0
Requires (Dev)
- laminas/laminas-coding-standard: ^2.3
- phpunit/phpunit: ^10.2
- psalm/plugin-phpunit: ^0.18.4
- squizlabs/php_codesniffer: ^3.7
- vimeo/psalm: ^5.13
README
本软件包提供了一个Mezzio Authentication适配器,用于使用结构良好的API密钥登录用户。
有关在您的 Mezzio 应用程序中使用身份验证中间件的概述,请参阅 mezzio/mezzio-authentication
的 介绍。
要使用此软件包来验证用户,您需要以下两样东西
- 一个用户存储库,用于处理将用户凭据与您的持久存储进行验证
- 您的 API 密钥前缀。此字符串被添加到您生成的密钥前面,以便于识别
请仔细选择您的前缀。它可能被像GitHub's Secret Scanner这样的工具用来查找泄露的密钥。它还应提供足够的信息,帮助用户和支持人员识别正确的密钥。在本例中,我们使用myco_sandbox
来同时展示密钥的来源(myco
)和使用该密钥的环境(sandbox
)。如果您曾经与 Stripe 集成,这种模式将是熟悉的。
Mezzio Authentication 默认提供了两个用户存储库:Htpasswd
和 PdoDatabase
。在本例中,我们将使用 PdoDatabase
。有关设置该存储库所需的额外步骤,请参阅PDO 配置文档。
安装
composer require kynx/mezzio-authentication-apikey
配置
配置可以存储在 /config/autoload/
文件夹下的文件中,也可以存储在您的应用程序或模块的 ConfigProvider
中。
要使用自动加载的配置,创建一个 config/autoload/api.global.php
文件,并添加以下内容:
<?php use Kynx\Mezzio\Authentication\ApiKey\ApiKeyAuthentication; use Mezzio\Authentication\AuthenticationInterface; use Mezzio\Authentication\UserRepository\PdoDatabase; use Mezzio\Authentication\UserRepositoryInterface; return [ 'authentication' => [ 'api-key' => [ 'primary' => [ 'prefix' => 'myco_sandbox', ], ], ], 'dependencies' => [ 'aliases' => [ AuthenticationInterface::class => ApiKeyAuthentication::class, UserRepositoryInterface::class => PdoDatabase::class, ], ], ];
或者,如果您的应用程序已经有一个 ConfigProvider
类,请将上述配置添加到该类中。
管道与路由
如果您的整个应用程序需要通过 API 密钥进行保护,请在 config/pipeline.php
中将身份验证中间件添加到在 DispatchMiddleware
管道之前的位置
$app->pipe(Mezzio\Authentication\AuthenticationMiddleware::class);
如果只有一些路由需要保护,请在 config/routes.php
中的各个路由管道中添加中间件
$app->get('/api/users', [ Mezzio\Authentication\AuthenticationMiddleware::class, Api\Action\Users::class ], 'api.users');
更改 API 密钥头
默认情况下,此软件包期望在 X-API-Key
请求头中找到 API 密钥。要使用不同的头名称,请将其添加到配置中
return [ 'authentication' => [ 'api-key' => [ 'header-name' => 'X-MyCo-Key', 'primary' => [ 'prefix' => 'myco_sandbox', ], ], ], // rest of config ];
高级配置
此软件包使用kynx/api-key-generator来解析和生成 API 密钥。这为设置密钥长度和使用的字符提供了许多选项 - 有关完整详细信息,请参阅该软件包的文档。默认值应该适用于大多数用例,但在需要时可以在配置中更改它们
use Kynx\ApiKey\RandomString; return [ 'authentication' => [ 'api-key' => [ 'primary' => [ 'prefix' => 'myco_sandbox', 'identifier-length' => 8, 'secret-length' => 36, 'characters' => RandomString::DEFAULT_CHARACTERS, ], ], ], // rest of config ];
请注意,**不建议**更改使用的字符!请参阅默认配置的注释。
后备配置
如果您已经向用户发放了密钥并修改了primary
密钥配置,现有密钥将无法使用。要继续支持旧密钥,请将旧设置添加到fallbacks
配置中。
use Kynx\ApiKey\RandomString; return [ 'authentication' => [ 'api-key' => [ 'primary' => [ 'prefix' => 'newco_sandbox', ], 'fallbacks' => [ [ 'prefix' => 'myco_sandbox', ], ], ], ], // rest of config ];
与密钥协同工作
kynx/api-key-generator提供了一个用于生成良好格式的API密钥的KeyGenerator
。只有使用与解析头部时相同的密钥生成器生成的密钥才能进行身份验证。
生成密钥
use Kynx\ApiKey\KeyGeneratorInterface; require 'vendor/autoload.php'; $container = require 'config/container.php'; $keyGenerator = $container->get(KeyGeneratorInterface::class); $apiKey = $keyGenerator->generate(); echo $apiKey->getKey();
这将输出一个API密钥供您与用户共享。类似于
myco_sandbox_Ez2FJvSAeRbLmLXYTyIzi8zSqxky6IXJ0VKxpqC8_69e51b54
存储密钥
生成的密钥包含用于从您的用户仓库中提取内容的函数。
ApiKey::getIdentifier()
返回用于查找用户的字符字符串。它有点像用户名。ApiKey::getSecret()
返回密钥的长的“密码”。
标识符应未散列并以区分大小写的方式存储。例如,在MySQL / MariaDB中,您可以在具有唯一索引的VARBINARY
列中存储它。
密钥的秘密信息必须在存储之前进行散列。使用PHP的password_hash()进行此操作。
为了支持API密钥的轮换,您应该在单独的表中存储密钥,并通过外键将其与用户记录关联起来。这样,用户就可以拥有多个密钥。MySQL的一个示例可能是
CREATE TABLE apikeys ( id INT UNSIGNED AUTO_INCREMENT PRIMARY KEY, user_id INT UNSIGNED NOT NULL, identifier VARBINARY(255) NOT NULL, hash VARCHAR(255) NOT NULL, created DATETIME NOT NULL, expires DATETIME NOT NULL, UNIQUE INDEX apikeys_identifier_udx (identifier), CONSTRAINT apikeys_user_fk FOREIGN KEY (user_id) REFERENCES users (id) ON DELETE CASCADE ON UPDATE CASCADE );