soapbox / signed-requests
一个包装器,用于向Laravel项目添加接受签名请求的能力。
5.1
2021-05-14 15:20 UTC
Requires
- php: ^7.3 || ^8.0
- guzzlehttp/guzzle: ^7.2
- illuminate/http: ^8.12
- illuminate/support: ^8.12
- nesbot/carbon: ^2.13
- ramsey/uuid: ^4.0
Requires (Dev)
- jshayes/fake-requests: dev-master
- mockery/mockery: ^1.4
- orchestra/testbench: ^6.3
- php-coveralls/php-coveralls: ^2.4
- phpunit/phpunit: ^9.3
README
一个包装器,用于向Laravel项目添加接受签名请求的能力。
安装
Composer
composer require soapbox/signed-requests
设置服务提供者
打开 config/app.php
并在应用程序提供者之上注册所需的服务提供者。
'providers' => [ ... SoapBox\SignedRequests\ServiceProvider::class ... ]
发布配置
php artisan vendor:publish --provider 'SoapBox\SignedRequests\ServiceProvider'
配置你的环境
你需要在你的环境中设置以下详细信息
SIGNED_REQUEST_ALGORITHM= SIGNED_REQUEST_CACHE_PREFIX= SIGNED_REQUEST_SIGNATURE_HEADER= SIGNED_REQUEST_ALGORITHM_HEADER= SIGNED_REQUEST_KEY= SIGNED_REQUEST_ALLOW_REPLAYS= SIGNED_REQUEST_TOLERANCE_SECONDS=
上述每个设置都允许不同级别的配置。
SIGNED_REQUEST_ALGORITHM
是用于生成/验证签名的算法。默认使用sha256
,你可以随意将其更改为hash_hmac
接受的任何内容。SIGNED_REQUEST_CACHE_PREFIX
是用于所有生成的缓存键的前缀。如果你不打算在多个应用程序之间共享缓存,这里可以使用默认值。SIGNED_REQUEST_SIGNATURE_HEADER
应该是包含签名的请求头,默认使用X-Signature
。SIGNED_REQUEST_ALGORITHM_HEADER
应该是包含用于签名请求的算法的请求头。SIGNED_REQUEST_KEY
是生成请求的应用程序和消耗请求的应用程序之间的共享密钥。此值不应公开。SIGNED_REQUEST_ALLOW_REPLAYS
允许你启用或禁用重放攻击。默认情况下,重放攻击被禁用。SIGNED_REQUEST_TOLERANCE_SECONDS
是请求将被考虑的秒数。此设置允许服务器之间有一定的时间漂移,仅在禁用重放攻击时使用。
设置中间件
Signed Requests 包含一个中间件,可以自动验证请求的签名。要开始,将以下中间件添加到你的 app/Http/Kernel.php
文件的 $routeMiddleware
属性中。
'verify-signature' => \SoapBox\SignedRequests\Middlewares\Laravel\VerifySignature::class
验证签名
verify-signature
中间件可以分配给路由,以验证传入请求的签名,以验证其真实性。
Route::get('/fire', function () { return "You'll only see this if the signature of the request is valid!"; })->middleware('verify-signature');
设置额外的密钥
你还可以设置额外的密钥,如果你想为不同的端点使用不同的密钥。
将它们添加到你的环境中
CUSTOM_SIGNED_REQUEST_ALGORITHM= CUSTOM_SIGNED_REQUEST_CACHE_PREFIX= CUSTOM_SIGNED_REQUEST_SIGNATURE_HEADER= CUSTOM_SIGNED_REQUEST_ALGORITHM_HEADER= CUSTOM_SIGNED_REQUEST_KEY= CUSTOM_SIGNED_REQUEST_ALLOW_REPLAYS= CUSTOM_SIGNED_REQUEST_TOLERANCE_SECONDS=
更新 signed-requests.php
中的配置
'default' => [ ... ], 'custom' => [ 'algorithm' => env('CUSTOM_SIGNED_REQUEST_ALGORITHM', 'sha256'), 'cache-prefix' => env('CUSTOM_SIGNED_REQUEST_CACHE_PREFIX', 'signed-requests'), 'headers' => [ 'signature' => env('CUSTOM_SIGNED_REQUEST_SIGNATURE_HEADER', 'X-Signature'), 'algorithm' => env('CUSTOM_SIGNED_REQUEST_ALGORITHM_HEADER', 'X-Signature-Algorithm') ], 'key' => env('CUSTOM_SIGNED_REQUEST_KEY', 'key'), 'request-replay' => [ 'allow' => env('CUSTOM_SIGNED_REQUEST_ALLOW_REPLAYS', false), 'tolerance' => env('CUSTOM_SIGNED_REQUEST_TOLERANCE_SECONDS', 30) ] ]
设置你的路由以使用自定义密钥。你传递的参数名称必须与在 signed-requests.php
中的配置中设置的密钥名称相同。
Route::get('/fire', function () { return "You'll only see this if the signature of the request is valid!"; })->middleware('verify-signature:custom');
签名 Postman 请求
如果你,像我们一样,喜欢使用 postman 在内部共享你的 API,你可以使用以下预请求脚本来自动签名你的 Postman 请求。
function guid() { function s4() { return Math.floor((1 + Math.random()) * 0x10000) .toString(16) .substring(1); } return s4() + s4() + '-' + s4() + '-' + s4() + '-' + s4() + '-' + s4() + s4() + s4(); } function getTimestamp() { var date = (new Date()).toISOString(); date = date.split("T"); date[1] = date[1].split(".")[0]; return date.join(' '); } postman.setEnvironmentVariable("x-signed-id", guid()); postman.setEnvironmentVariable("x-signed-timestamp", getTimestamp()); postman.setEnvironmentVariable("x-algorithm", "sha256"); var payload = { "id": postman.getEnvironmentVariable("x-signed-id"), "method": request.method, "timestamp": postman.getEnvironmentVariable("x-signed-timestamp"), "uri": request.url.replace("{{url}}", postman.getEnvironmentVariable("url")), "content": (Object.keys(request.data).length === 0) ? "" : JSON.stringify(JSON.parse(request.data)) }; var hash = CryptoJS.HmacSHA256(JSON.stringify(payload), postman.getEnvironmentVariable("key")); var signature = hash.toString(); postman.setEnvironmentVariable("x-signature", signature);
注意,为了使此功能正常工作,你必须设置你的环境以包含以下变量
{{url}}
这是你要调用的 API 的基础 URL。{{key}}
这是你在环境中使用的共享密钥。
所有其他需要的环境变量将由上面的脚本自动生成。