jeremykendall / query-auth
REST API查询认证的签名生成和验证
Requires
- php: >=5.3.2
- ircmaxell/random-lib: v1.0.0
Requires (Dev)
- phpunit/phpunit: 3.7.*
This package is auto-updated.
Last update: 2024-08-25 05:57:41 UTC
README
REST API查询认证的签名生成和验证
API查询认证
大多数API需要某种形式的查询认证,通常是通过使用API密钥和签名来签名API请求。签名通常使用共享密钥生成。当你消费API时,创建签名通常有(希望是)易于遵循的步骤。当你编写自己的API时,你必须为服务器端签名验证策略和客户端签名创建策略。这个库旨在为你处理这两个任务。
示例实现
一个Query Auth库的示例实现可用,以更好地展示如何使用该库。
用法
该库有三个组件
- 请求签名
- 请求验证
- API密钥和密钥生成
请求签名和验证是通过使用请求适配器实现的。
请求适配器
Query Auth请求适配器封装出发和到达的请求,并将它们适配到Query Auth期望的请求接口。
出发
出发请求适配器用于促进请求签名。目前,在QueryAuth\Request\Adapter\Outgoing
命名空间中有两个可用
GuzzleRequestAdapter
用于Guzzle v3GuzzleHttpRequestAdapter
用于Guzzle v4
到达
到达请求适配器用于促进请求验证。目前,在QueryAuth\Request\Adapter\Incoming
命名空间中有一个可用
SlimRequestAdapter
用于Slim PHP v2
自定义
如果你希望使用除了Guzzle之外的HTTP库,或者如果你希望使用除了Slim之外的应用程序框架,你需要编写自己的请求适配器。请参阅现有的请求适配器以获取示例。
请求签名
use GuzzleHttp\Client as GuzzleHttpClient; use QueryAuth\Credentials\Credentials; use QueryAuth\Factory; use QueryAuth\Request\Adapter\Outgoing\GuzzleHttpRequestAdapter; $factory = new Factory(); $requestSigner = $factory->newRequestSigner(); $credentials = new Credentials('key', 'secret'); // Create a GET request and set an endpoint $guzzle = new GuzzleHttpClient(['base_url' => 'http://api.example.com']); $request = $guzzle->createRequest('GET', '/endpoint'); // Sign the request $requestSigner->signRequest(new GuzzleHttpRequestAdapter($request), $credentials); // Send signed request $response = $guzzle->send($request);
请求验证
use QueryAuth\Credentials\Credentials; use QueryAuth\Factory; use QueryAuth\Request\Adapter\Incoming\SlimRequestAdapter; $factory = new Factory(); $requestValidator = $factory->newRequestValidator(); $credentials = new Credentials('key', 'secret'); // Get the Slim request (in the context of a Slim route, hook, or middleware) $request = $app->request; // $isValid is a boolean $isValid = $requestValidator->isValid(new SlimRequestAdapter($request), $credentials);
RequestValidator::isValid()
将返回true或false。它也可能抛出三种异常之一
DriftExceededException
:如果时间戳超出+-RequestValidator::$drift
SignatureMissingException
:如果请求参数中缺少签名TimestampMissingException
:如果请求参数中缺少时间戳
Drift默认为15秒,这意味着有一个30秒的窗口,在此期间请求是有效的。默认值可以通过使用RequestValidator::setDrift()
修改。
重放攻击预防
有许多策略可用于防止重放攻击。这里实施的策略遵循以下一般概述
- 验证到达签名
- 如果签名有效,检查存储层以查看该组合的API密钥和签名是否之前已经使用过
- 如果已使用,则请求可能是重放攻击,应拒绝
- 如果尚未设置,则持续使用API密钥、签名和过期时间戳
- 定期清除超出过期时间戳的记录
重要:签名过期时间戳应大于最大允许的漂移。过早删除签名可能会使您容易受到重放攻击。
注意:实现重放攻击预防策略是可选的。这不是使用此库的要求。然而,非常推荐。
提供了QueryAuth\Storage\SignatureStorage
接口,以帮助实现重放攻击预防。
<?php namespace QueryAuth\Storage; interface SignatureStorage { public function exists($key, $signature); public function save($key, $signature, $expires); public function purge(); }
注意:实现SignatureStorage
接口不是防止重放攻击的要求,它只是用于协助您实现上述策略的辅助工具。
密钥生成
您可以使用以下方式生成API密钥和密钥。
$factory = new QueryAuth\Factory(); $keyGenerator = $factory->newKeyGenerator(); // 40 character random alphanumeric string $key = $keyGenerator->generateKey(); // 60 character random string containing the characters // 0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ./ $secret = $keyGenerator->generateSecret();
键和密钥都使用Anthony Ferrara的RandomLib随机字符串生成器生成。
低于3.0+的版本已弃用,但未作废
虽然我建议尽快升级到v3,但在重构API而不更改签名创建和验证逻辑的情况下,一个令人愉快的副作用是Query Auth 3.0+与Query Auth的早期版本兼容。这意味着您可以在服务器端(验证)升级Query Auth,而无需立即升级所有客户端(创建)应用程序。额外奖励!
安装
包安装由Composer处理。
- 如果您尚未安装,请安装Composer
- 在项目的根目录中创建
composer.json
,并将query-auth添加为依赖项
{ "require": { "jeremykendall/query-auth": "*" } }
- 运行
composer install
- 在您的引导/初始化脚本中需要Composer的
vendor/autoload.php
脚本
反馈和贡献
- 欢迎以拉取请求和/或问题的形式提供反馈。
- 贡献应一般遵循"向项目贡献"中概述的策略。
- 请针对
develop
分支提交拉取请求
鸣谢
-
Query Auth是我对Signature Version 2实现的个人实现,该实现来自AWS SDK for PHP 2。因此,此分发包含Apache License Version 2.0的一个版本,以及AWS SDK for PHP 2 NOTICE文件的相关部分。
-
API密钥和API密钥生成由Anthony Ferrara的RandomLib随机字符串生成器处理。