hyperf接口签名算法
时间: 2023-10-03 18:05:32 浏览: 52
在 Hyperf 中实现接口签名算法,可以保证接口的安全性,防止非法请求。具体实现步骤如下:
1. 在 config/autoload 文件夹下创建一个 signature.php 配置文件,用于存储签名相关的配置信息。例如:
```
<?php
return [
'secret_key' => env('SIGNATURE_SECRET_KEY', 'your_secret_key'),
'timeout' => env('SIGNATURE_TIMEOUT', 60),
];
```
其中,secret_key 是用于签名的密钥,timeout 是签名的有效期(单位为秒)。
2. 创建一个 SignatureService 类,用于生成和验证签名。例如:
```
<?php
declare(strict_types=1);
namespace App\Service;
use Hyperf\Utils\Codec\Json;
use Hyperf\Utils\Str;
class SignatureService
{
/**
* 生成签名
*
* @param array $data 需要进行签名的数据
* @param int $timestamp 时间戳
* @return string
*/
public function generate(array $data, int $timestamp): string
{
// 将数据按照字典序排序,拼接成字符串
ksort($data);
$dataStr = http_build_query($data);
// 将时间戳拼接到数据字符串的末尾
$dataStr .= '&' . $timestamp;
// 使用密钥对数据字符串进行HMAC-SHA256加密,生成签名
$secretKey = config('signature.secret_key');
$signature = hash_hmac('sha256', $dataStr, $secretKey);
return $signature;
}
/**
* 验证签名
*
* @param string $signature 签名
* @param array $data 需要进行签名的数据
* @param int $timestamp 时间戳
* @return bool
*/
public function verify(string $signature, array $data, int $timestamp): bool
{
// 计算签名
$expectedSignature = $this->generate($data, $timestamp);
// 验证签名是否一致
return hash_equals($signature, $expectedSignature);
}
/**
* 从请求参数中获取签名
*
* @param array $params 请求参数
* @return string|null
*/
public function getSignature(array $params): ?string
{
return $params['signature'] ?? null;
}
/**
* 从请求参数中获取时间戳
*
* @param array $params 请求参数
* @return int|null
*/
public function getTimestamp(array $params): ?int
{
return $params['timestamp'] ?? null;
}
/**
* 从请求参数中获取业务数据
*
* @param array $params 请求参数
* @return array|null
*/
public function getData(array $params): ?array
{
$dataJson = $params['data'] ?? null;
if (! $dataJson) {
return null;
}
return Json::decode($dataJson, true);
}
/**
* 生成请求参数
*
* @param array $data 业务数据
* @return array
*/
public function generateParams(array $data): array
{
$timestamp = time();
$signature = $this->generate($data, $timestamp);
return [
'data' => Json::encode($data),
'timestamp' => $timestamp,
'signature' => $signature,
];
}
/**
* 验证请求参数
*
* @param array $params 请求参数
* @return bool
*/
public function verifyParams(array $params): bool
{
$signature = $this->getSignature($params);
$timestamp = $this->getTimestamp($params);
$data = $this->getData($params);
if (! $signature || ! $timestamp || ! $data) {
return false;
}
// 验证签名是否正确,并且验证签名是否过期
$timeout = config('signature.timeout', 60);
$currentTime = time();
return $this->verify($signature, $data, $timestamp) && ($currentTime - $timestamp) <= $timeout;
}
}
```
在 SignatureService 类中,generate 方法用于生成签名,verify 方法用于验证签名,getSignature、getTimestamp 和 getData 方法用于从请求参数中获取签名、时间戳和业务数据,generateParams 方法用于生成请求参数,verifyParams 方法用于验证请求参数是否正确。
3. 在控制器中使用 SignatureService 类进行接口签名的生成和验证。例如:
```
<?php
declare(strict_types=1);
namespace App\Controller;
use App\Service\SignatureService;
use Hyperf\HttpServer\Annotation\AutoController;
use Hyperf\HttpServer\Annotation\Middleware;
use Hyperf\HttpServer\Annotation\MiddlewareRegister;
/**
* @AutoController()
* @MiddlewareRegister(SignatureMiddleware::class)
*/
class ApiController extends Controller
{
/**
* @Middleware(SignatureMiddleware::class)
*/
public function index(SignatureService $signatureService)
{
// 从请求参数中获取业务数据
$params = $this->request->all();
$data = $signatureService->getData($params);
// 处理业务逻辑
// ...
// 返回结果
return $this->success([
'data' => $data,
]);
}
/**
* @Middleware(SignatureMiddleware::class)
*/
public function test(SignatureService $signatureService)
{
// 从请求参数中获取业务数据
$params = $this->request->all();
$data = $signatureService->getData($params);
// 处理业务逻辑
// ...
// 返回结果
return $this->success([
'data' => $data,
]);
}
}
```
在 ApiController 控制器中,使用 @MiddlewareRegister(SignatureMiddleware::class) 注解表示需要使用 SignatureMiddleware 中间件进行接口签名的验证,使用 SignatureService 类进行签名的生成和验证。
4. 创建 SignatureMiddleware 中间件,用于验证接口签名。例如:
```
<?php
declare(strict_types=1);
namespace App\Middleware;
use App\Service\SignatureService;
use Hyperf\HttpMessage\Stream\SwooleStream;
use Hyperf\HttpServer\Contract\RequestInterface;
use Hyperf\HttpServer\Contract\ResponseInterface;
use Hyperf\Utils\Codec\Json;
use Psr\Http\Message\ResponseInterface as PsrResponseInterface;
use Psr\Http\Message\ServerRequestInterface;
use Psr\Http\Server\MiddlewareInterface;
use Psr\Http\Server\RequestHandlerInterface;
class SignatureMiddleware implements MiddlewareInterface
{
/**
* @var SignatureService
*/
protected $signatureService;
public function __construct(SignatureService $signatureService)
{
$this->signatureService = $signatureService;
}
public function process(ServerRequestInterface $request, RequestHandlerInterface $handler): PsrResponseInterface
{
// 验证请求参数是否正确
$params = $request->getQueryParams();
if (! $this->signatureService->verifyParams($params)) {
// 请求参数错误,返回 400 错误
$response = make(ResponseInterface::class);
return $response->withStatus(400);
}
// 验证通过,将业务数据保存到请求中
$data = $this->signatureService->getData($params);
$request = $request->withParsedBody($data);
return $handler->handle($request);
}
}
```
在 SignatureMiddleware 中间件中,使用 SignatureService 类进行接口签名的验证,如果签名验证失败,则返回 400 错误;如果验证通过,则将业务数据保存到请求中,以便后续方法进行业务处理。
通过以上步骤,你就可以在 Hyperf 中实现接口签名算法,确保接口的安全性。