openApiService = $openApiService; $this->authService = $authService; } /** * 处理请求 * * @param Request $request * @param Closure $next * @param string|null $scope * @return mixed */ public function handle(Request $request, Closure $next, string $scope = null) { try { // 获取认证信息 $authInfo = $this->extractAuthInfo($request); if (!$authInfo) { return $this->unauthorizedResponse('缺少认证信息'); } // 验证应用 $app = $this->validateApp($authInfo); if (!$app) { return $this->unauthorizedResponse('应用认证失败'); } // 检查权限范围 if ($scope && !$this->openApiService->checkScope($app, $scope)) { return $this->forbiddenResponse('权限不足'); } // 检查IP白名单 if (!$this->openApiService->checkIpWhitelist($app, $request->ip())) { return $this->forbiddenResponse('IP地址不在白名单中'); } // 将应用信息添加到请求中 $request->attributes->set('openapi_app', $app); $request->attributes->set('openapi_auth_type', $authInfo['type']); // 更新最后使用时间 $this->openApiService->updateLastUsed($app); return $next($request); } catch (\Exception $e) { return $this->errorResponse('认证过程中发生错误: ' . $e->getMessage()); } } /** * 提取认证信息 * * @param Request $request * @return array|null */ protected function extractAuthInfo(Request $request): ?array { // API Key认证 if ($apiKey = $this->extractApiKey($request)) { return [ 'type' => AUTH_TYPE::API_KEY, 'app_id' => $apiKey['app_id'], 'app_secret' => $apiKey['app_secret'], ]; } // Bearer Token认证 if ($token = $this->extractBearerToken($request)) { return [ 'type' => AUTH_TYPE::BEARER, 'token' => $token, ]; } // Basic认证 if ($basic = $this->extractBasicAuth($request)) { return [ 'type' => AUTH_TYPE::BASIC, 'app_id' => $basic['username'], 'app_secret' => $basic['password'], ]; } // 签名认证 if ($signature = $this->extractSignature($request)) { return [ 'type' => AUTH_TYPE::SIGNATURE, 'app_id' => $signature['app_id'], 'signature' => $signature['signature'], 'timestamp' => $signature['timestamp'], ]; } return null; } /** * 提取API Key * * @param Request $request * @return array|null */ protected function extractApiKey(Request $request): ?array { $headerName = config('openapi.auth.api_key.header_name', 'X-API-Key'); $queryParam = config('openapi.auth.api_key.query_param', 'api_key'); // 从Header获取 $apiKey = $request->header($headerName); // 从Query参数获取 if (!$apiKey) { $apiKey = $request->query($queryParam); } if (!$apiKey) { return null; } // 解析API Key格式:app_id:app_secret if (strpos($apiKey, ':') !== false) { list($appId, $appSecret) = explode(':', $apiKey, 2); return [ 'app_id' => $appId, 'app_secret' => $appSecret, ]; } // 如果只有一个值,尝试从数据库查找 return [ 'app_id' => $apiKey, 'app_secret' => null, ]; } /** * 提取Bearer Token * * @param Request $request * @return string|null */ protected function extractBearerToken(Request $request): ?string { $authorization = $request->header('Authorization'); if (!$authorization || !str_starts_with($authorization, 'Bearer ')) { return null; } return substr($authorization, 7); } /** * 提取Basic认证 * * @param Request $request * @return array|null */ protected function extractBasicAuth(Request $request): ?array { $authorization = $request->header('Authorization'); if (!$authorization || !str_starts_with($authorization, 'Basic ')) { return null; } $credentials = base64_decode(substr($authorization, 6)); if (strpos($credentials, ':') === false) { return null; } list($username, $password) = explode(':', $credentials, 2); return [ 'username' => $username, 'password' => $password, ]; } /** * 提取签名认证 * * @param Request $request * @return array|null */ protected function extractSignature(Request $request): ?array { $signatureHeader = config('openapi.auth.signature.header_name', 'X-Signature'); $timestampHeader = config('openapi.auth.signature.timestamp_header', 'X-Timestamp'); $signature = $request->header($signatureHeader); $timestamp = $request->header($timestampHeader); $appId = $request->header('X-App-Id'); if (!$signature || !$timestamp || !$appId) { return null; } return [ 'app_id' => $appId, 'signature' => $signature, 'timestamp' => $timestamp, ]; } /** * 验证应用 * * @param array $authInfo * @return \App\Module\OpenAPI\Models\OpenApiApp|null */ protected function validateApp(array $authInfo) { switch ($authInfo['type']) { case AUTH_TYPE::API_KEY: case AUTH_TYPE::BASIC: return $this->authService->validateApiKey( $authInfo['app_id'], $authInfo['app_secret'] ); case AUTH_TYPE::BEARER: return $this->authService->validateBearerToken($authInfo['token']); case AUTH_TYPE::SIGNATURE: return $this->authService->validateSignature( $authInfo['app_id'], $authInfo['signature'], $authInfo['timestamp'], request() ); default: return null; } } /** * 返回未授权响应 * * @param string $message * @return Response */ protected function unauthorizedResponse(string $message): Response { return response()->json([ 'error' => 'Unauthorized', 'message' => $message, 'code' => 401, ], 401); } /** * 返回禁止访问响应 * * @param string $message * @return Response */ protected function forbiddenResponse(string $message): Response { return response()->json([ 'error' => 'Forbidden', 'message' => $message, 'code' => 403, ], 403); } /** * 返回错误响应 * * @param string $message * @return Response */ protected function errorResponse(string $message): Response { return response()->json([ 'error' => 'Internal Server Error', 'message' => $message, 'code' => 500, ], 500); } }