soapbox/signed-requests

一个包装器,用于向Laravel项目添加接受签名请求的能力。

5.1 2021-05-14 15:20 UTC

This package is auto-updated.

Last update: 2024-08-28 16:58:12 UTC


README

Build Status Coverage Status Code Climate

一个包装器,用于向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}} 这是你在环境中使用的共享密钥。

所有其他需要的环境变量将由上面的脚本自动生成。