**/ namespace app\api\middleware; use think\facade\Config; use think\exception\HttpResponseException; use think\Response; class Allow { public function handle($request, \Closure $next) { // 处理跨域 header('Access-Control-Allow-Origin: *'); header('Access-Control-Max-Age: 1800'); header('Access-Control-Allow-Methods: GET, POST, PATCH, PUT, DELETE'); header('Access-Control-Allow-Headers: Authorization, Content-Type, If-Match, If-Modified-Since, If-None-Match, If-Unmodified-Since, X-CSRF-TOKEN, X-Requested-With,access-token,token,adid,clickid,client'); // 第一次预请求不管 if (strtoupper($request->method()) == "OPTIONS") { exit; } // 对GET请求进行签名验证 if (strtoupper($request->method()) == "GET") { $this->verifySignature($request); } // 处理跨域 // 后置中间件 $response = $next($request); return $response; } /** * 验证请求签名 * @param \think\Request $request * @return void */ protected function verifySignature($request) { // 获取所有GET参数 $params = $request->get(); // 如果请求中携带is_test=true参数,则跳过签名验证 if (isset($params['is_test']) && $params['is_test'] === 'true') { return; } // 检查是否有必要的签名参数 if (!isset($params['timestamp']) || !isset($params['sign'])) { $this->error('缺少必要的签名参数'); } // 检查请求时间戳是否在合理范围内(例如5分钟内) if (time() - intval($params['timestamp']) > 300) { $this->error('请求已过期'); } // 从请求中获取签名 $requestSign = $params['sign']; //移除url unset($params['s']); // 从参数中移除签名,用于生成本地签名 unset($params['sign']); // 按照键名对参数进行排序 ksort($params); // 组合参数为字符串 $signStr = ''; foreach ($params as $key => $value) { $signStr .= $key . '=' . $value . '&'; } // 获取当前请求的域名和时间戳,组合为密钥 $host = $request->host(); $timestamp = $params['timestamp']; $appSecret = $host . $timestamp; // 添加密钥 $signStr = rtrim($signStr, '&') . $appSecret; // 生成本地签名(使用MD5签名算法) $localSign = md5($signStr); // 比对签名 if ($requestSign !== $localSign) { $this->error('签名验证失败'); } } /** * 返回错误信息 * @param string $msg 错误信息 * @param int $code 错误码 * @return void */ protected function error($msg, $code = 0) { $result = [ 'status' => $code, 'msg' => $msg, 'data' => null ]; $response = Response::create($result, 'json', $code); throw new HttpResponseException($response); } /** * 中间件结束调度 * @param \think\Response $response * @return void */ public function end(\think\Response $response) { } }