使用 HMAC 密钥保护 API
注意
为了本说明文档的目的,并为了与授权令牌保持一致性,术语“令牌”将用于表示一组 API 密钥(密钥和 secretKey)。
HMAC 密钥可用于对您自己的网站的用户进行身份验证,或在允许第三方开发人员访问您的 API 时使用。使用 HMAC 密钥发出请求时,令牌应包含在 Authorization
头中,作为 HMAC-SHA256
令牌。
注意
默认情况下,$authenticatorHeader['hmac']
设置为 Authorization
。您可以通过在 app/Config/AuthToken.php 配置文件中设置 $authenticatorHeader['hmac']
值来更改此值。
令牌通过用户上的 generateHmacToken()
方法发出。这将返回一个 CodeIgniter\Shield\Entities\AccessToken
实例。返回的 AccessToken
对象将包含一个 secret
字段,该字段将是“密钥”,以及一个 rawSecretKey
字段,该字段将是“secretKey”。您应立即向您的用户显示“secretKey”,以便他们有机会将其复制到安全的地方,因为这是您唯一可以显示此密钥的时间。“密钥”和“secretKey”将保存到数据库中。“secretKey”以加密形式存储。
generateHmacToken()
方法需要一个令牌名称。这些是自由字符串,通常用于标识从中/为其生成令牌的用户/设备,例如“Johns MacBook Air”。
$routes->get('hmac/token', static function () {
$token = auth()->user()->generateHmacToken(service('request')->getVar('token_name'));
return json_encode(['key' => $token->secret, 'secretKey' => $token->rawSecretKey]);
});
您可以使用该用户上的 hmacTokens()
方法访问所有用户的 HMAC 密钥。
$tokens = $user->hmacTokens();
foreach ($tokens as $token) {
//
}
用法
为了使用 HMAC 密钥/令牌,请求中的 Authorization
标头将设置为以下内容
Authorization: HMAC-SHA256 <key>:<HMAC HASH of request body>
执行此操作的代码看起来像这样
header("Authorization: HMAC-SHA256 {$key}:" . hash_hmac('sha256', $requestBody, $secretKey));
HMAC 密钥权限
可以为 HMAC 密钥提供 scopes
,这基本上是 HMAC 令牌/密钥的权限字符串。这通常与用户拥有的权限不同,但用于指定 API 本身的权限。如果未指定,则令牌将被授予对所有范围的所有访问权限。对于较小的 API,这可能就足够了。
$token = $user->generateHmacToken('token-name', ['users-read']);
return json_encode(['key' => $token->secret, 'secretKey' => $token->rawSecretKey]);
注意
此时,范围名称应避免使用冒号 (:
),因为这会导致路由过滤器无法正确识别。
在处理传入请求时,您可以使用 hmacTokenCan()
方法检查令牌是否已被授予对范围的访问权限。
if ($user->hmacTokenCan('users-read')) {
//
}
撤销密钥/令牌
可以通过使用 revokeHmacToken($key)
或 revokeAllHmacTokens()
方法从数据库中删除令牌来撤销令牌。
$user->revokeHmacToken($key);
$user->revokeAllHmacTokens();
HMAC 密钥加密
HMAC 密钥存储为加密形式。在开始使用 HMAC 之前,您需要在 app/Config/AuthToken.php 中的 $hmacEncryptionKeys
中设置/覆盖加密密钥。这应使用 .env 和/或系统环境变量进行设置。有关如何执行此操作的说明,请参阅 CodeIgniter 4 文档中的 设置加密密钥 部分。
您还将能够调整默认驱动程序 $hmacEncryptionDefaultDriver
和默认摘要 $hmacEncryptionDefaultDigest
,它们分别默认为 'OpenSSL'
和 'SHA512'
。
有关设置这些值的更多详细信息,请参阅 HMAC SHA256 令牌身份验证器。
加密密钥轮换
有关如何设置、轮换加密密钥和重新加密现有 HMAC 'secretKey'
值的信息,请参阅 HMAC SHA256 令牌身份验证器。
保护路由
指定受保护路由的第一种方法是使用 hmac
控制器过滤器。
例如,为了确保它保护 /api
路由组下的所有路由,您将使用 app/Config/Filters.php 上的 $filters
设置。
public $filters = [
'hmac' => ['before' => ['api/*']],
];
您还可以在路由文件本身中指定过滤器应在一个或多个路由上运行
$routes->group('api', ['filter' => 'hmac'], function($routes) {
//
});
$routes->get('users', 'UserController::list', ['filter' => 'hmac:users-read']);
当过滤器运行时,它会检查 Authorization
头部以查找具有计算令牌的 HMAC-SHA256
值。然后它解析原始令牌,并在数据库中查找 key
部分。找到后,它将重新散列请求的主体以验证 Authorization 原始令牌的其余部分。如果它通过签名测试,它可以确定正确的用户,然后可以通过 auth()->user()
调用获得该用户。
注意
目前只能在路由过滤器上使用单个作用域。如果传入多个作用域,则只检查第一个作用域。