| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657 |
- <?php
-
- namespace app\common\middleware;
-
- use think\facade\Cache;
- use think\Response;
-
- class SignatureMiddleware
- {
- public function handle($request, \Closure $next)
- {
- // 1. 获取加密签名
- $sign = $request->header('X-Sign');
- if (!$sign) {
- return $this->reject('缺少签名', 401);
- }
-
- // 2. 读取私钥
- $privateKey = file_get_contents(env('RSA_PRIVATE_KEY_PATH'));
- if (!$privateKey) {
- return $this->reject('服务器密钥错误', 500);
- }
-
- // 3. 解密数据
- $decrypted = '';
- openssl_private_decrypt(base64_decode($sign), $decrypted, $privateKey);
-
- if (!$decrypted || !strpos($decrypted, ':')) {
- return $this->reject('无效签名', 403);
- }
-
- // 4. 分离随机数和时间戳
- list($nonce, $timestamp) = explode(':', $decrypted, 2);
-
- // 5. 验证时间有效性(5分钟内)
- if (abs(time() - $timestamp / 1000) > 300) {
- return $this->reject('请求已过期', 403);
- }
-
- // 6. 防重放攻击(检查nonce唯一性)
- $cacheKey = 'nonce_' . $nonce;
- if (Cache::has($cacheKey)) {
- return $this->reject('重复请求', 403);
- }
- Cache::set($cacheKey, 1, 300); // 5分钟缓存
-
- return $next($request);
- }
-
- private function reject($msg, $code): Response
- {
- return Response::create([
- 'code' => $code,
- 'msg' => $msg
- ], 'json')->code($code);
- }
- }
|