| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279 |
- <?php
- declare (strict_types=1);
- namespace app\middleware;
- use app\common\model\system\ApiRequestLog;
- use crmeb\services\JwtTokenService;
- use think\facade\Request;
- use think\Response;
- class ApiRequestLogMiddleware
- {
- /**
- * 处理请求
- *
- * @param \think\Request $request
- * @param \Closure $next
- * @return Response
- */
- public function handle($request, \Closure $next)
- {
- // 记录请求开始时间
- $startTime = microtime(true);
-
- // 执行请求
- $response = $next($request);
-
- // 记录请求结束时间和计算响应时间
- $endTime = microtime(true);
- $responseTime = (int)(($endTime - $startTime) * 1000); // 转换为毫秒
-
- try {
- // 获取应用类型
- $appType = $this->getAppType($request);
-
- // 从token中获取所有用户信息
- $userInfo = $this->getUserInfoFromToken($request);
- $userId = $userInfo['userId'] ?? 0;
- $merchantId = $userInfo['merchantId'] ?? 0;
- $adminId = $userInfo['adminId'] ?? 0;
- // 记录请求日志
- ApiRequestLog::record([
- 'app_type' => $appType,
- 'request_method' => $request->method(),
- 'request_url' => $request->url(),
- 'request_params' => $this->getRequestParams($request),
- 'request_headers' => $this->getRequestHeaders($request),
- 'request_ip' => $request->ip(),
- 'user_agent' => $request->header('user-agent', ''),
- 'user_id' => $userId,
- 'merchant_id' => $merchantId,
- 'admin_id' => $adminId,
- 'response_code' => $response->getCode(),
- 'response_data' => $this->getResponseData($response),
- 'response_time' => $responseTime,
- 'error_message' => $this->getErrorMessage($response),
- ]);
- } catch (\Exception $e) {
- // 记录日志失败时不中断主流程
- // 可以在这里添加日志记录失败的日志
- }
-
- return $response;
- }
- /**
- * 获取应用类型
- * @param \think\Request $request
- * @return string
- */
- private function getAppType($request): string
- {
- // 获取请求路径
- $path = $request->pathinfo();
- $position = strpos($path, '/');
- if ($position === false) {
- return 'unknown';
- }
- return substr($path, 0, $position);
- }
- /**
- * 获取请求参数
- * @param \think\Request $request
- * @return array
- */
- private function getRequestParams($request): array
- {
- $params = $request->param();
-
- // 过滤敏感信息
- $sensitiveFields = ['password', 'pwd', 'token', 'secret', 'key', 'authorization'];
- foreach ($sensitiveFields as $field) {
- if (isset($params[$field])) {
- $params[$field] = '***';
- }
- }
-
- return $params;
- }
- /**
- * 获取请求头信息
- * @param \think\Request $request
- * @return array
- */
- private function getRequestHeaders($request): array
- {
- $headers = $request->header();
-
- // 过滤敏感头信息
- $sensitiveHeaders = ['authorization', 'cookie', 'token'];
- foreach ($sensitiveHeaders as $header) {
- if (isset($headers[$header])) {
- $headers[$header] = '***';
- }
- }
-
- return $headers;
- }
- /**
- * 获取响应数据
- * @param Response $response
- * @return array|null
- */
- private function getResponseData(Response $response): ?array
- {
- $content = $response->getContent();
-
- try {
- $data = json_decode($content, true);
- if (json_last_error() === JSON_ERROR_NONE) {
- return $data;
- }
- } catch (\Exception $e) {
- // JSON解析失败,返回原始内容的前1000个字符
- return ['raw_content' => substr($content, 0, 1000)];
- }
-
- return null;
- }
- /**
- * 获取错误信息
- * @param Response $response
- * @return string
- */
- private function getErrorMessage(Response $response): string
- {
- if ($response->getCode() >= 400) {
- $content = $response->getContent();
- try {
- $data = json_decode($content, true);
- if (json_last_error() === JSON_ERROR_NONE && isset($data['msg'])) {
- return $data['msg'];
- }
- } catch (\Exception $e) {
- return substr($content, 0, 500);
- }
- }
-
- return '';
- }
- /**
- * 从token中解析adminId
- * @param \think\Request $request
- * @return int
- */
- private function getAdminIdFromToken($request): int
- {
- try {
- $token = $this->getTokenFromRequest($request);
- if (!$token) {
- return 0;
- }
-
- $jwtService = new JwtTokenService();
-
- try {
- // 尝试解析token
- $payload = $jwtService->parseToken($token);
- } catch (\Exception $e) {
- // 如果解析失败,尝试解码(不验证签名)
- $payload = $jwtService->decode($token);
- }
-
- // 检查token类型是否为admin,并且包含有效的ID
- if (isset($payload->jti) && is_array($payload->jti) && count($payload->jti) >= 2) {
- if ($payload->jti[1] === 'admin') {
- return (int)$payload->jti[0];
- }
- }
- } catch (\Exception $e) {
- // token解析失败,返回0
- return 0;
- }
-
- return 0;
- }
- /**
- * 从请求中获取token
- * @param \think\Request $request
- * @return string|null
- */
- private function getTokenFromRequest($request): ?string
- {
- // 从header中获取token
- $token = $request->header('X-Token');
- if ($token && strpos($token, 'Bearer ') === 0) {
- $token = substr($token, 7);
- }
-
- // 如果header中没有,尝试从参数中获取
- if (!$token) {
- $token = $request->param('token');
- }
-
- return $token ? trim($token) : null;
- }
- /**
- * 从token中获取所有用户信息
- * @param \think\Request $request
- * @return array
- */
- private function getUserInfoFromToken($request): array
- {
- $result = [
- 'userId' => 0,
- 'merchantId' => 0,
- 'adminId' => 0
- ];
-
- try {
- $token = $this->getTokenFromRequest($request);
- if (!$token) {
- return $result;
- }
-
- $jwtService = new JwtTokenService();
-
- try {
- // 尝试解析token
- $payload = $jwtService->parseToken($token);
- } catch (\Exception $e) {
- // 如果解析失败,尝试解码(不验证签名)
- $payload = $jwtService->decode($token);
- }
-
- // 检查token类型并获取对应的ID
- if (isset($payload->jti) && is_array($payload->jti) && count($payload->jti) >= 2) {
- $userId = (int)$payload->jti[0];
- $userType = $payload->jti[1];
-
- switch ($userType) {
- case 'user':
- $result['userId'] = $userId;
- break;
- case 'mer':
- $result['merchantId'] = $userId;
- break;
- case 'admin':
- $result['adminId'] = $userId;
- break;
- }
- }
- } catch (\Exception $e) {
- // token解析失败,返回默认值
- }
-
- return $result;
- }
- }
|