| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315 |
- <?php
- namespace App\Module\OpenAPI\Middleware;
- use App\Module\OpenAPI\Services\OpenApiService;
- use App\Module\OpenAPI\Services\AuthService;
- use App\Module\OpenAPI\Enums\AUTH_TYPE;
- use Closure;
- use Illuminate\Http\Request;
- use Illuminate\Http\Response;
- /**
- * API认证中间件
- */
- class ApiAuthMiddleware
- {
- /**
- * @var OpenApiService
- */
- protected OpenApiService $openApiService;
- /**
- * @var AuthService
- */
- protected AuthService $authService;
- public function __construct(OpenApiService $openApiService, AuthService $authService)
- {
- $this->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);
- }
- }
|