addError($arg, 'API密钥不能为空'); return; } // 检查API密钥格式(app_id:app_secret) if (!str_contains($apiKey, ':')) { $this->addError($arg, 'API密钥格式错误,应为 app_id:app_secret 格式'); return; } $parts = explode(':', $apiKey, 2); if (count($parts) !== 2) { $this->addError($arg, 'API密钥格式错误'); return; } [$appId, $appSecret] = $parts; if (empty($appId) || empty($appSecret)) { $this->addError($arg, 'API密钥的应用ID和密钥都不能为空'); return; } // 验证应用ID格式(32位字符) if (strlen($appId) !== 32 || !ctype_alnum($appId)) { $this->addError($arg, '应用ID格式错误'); return; } // 验证应用密钥格式(64位字符) if (strlen($appSecret) !== 64 || !ctype_alnum($appSecret)) { $this->addError($arg, '应用密钥格式错误'); return; } } /** * 验证JWT令牌格式 * * @param string $token * @param string $arg * @return void */ public function validateJwtToken(string $token, string $arg): void { if (empty($token)) { $this->addError($arg, 'JWT令牌不能为空'); return; } // JWT令牌应该有3个部分,用.分隔 $parts = explode('.', $token); if (count($parts) !== 3) { $this->addError($arg, 'JWT令牌格式错误'); return; } // 验证每个部分都是有效的base64编码 foreach ($parts as $index => $part) { if (empty($part)) { $this->addError($arg, 'JWT令牌格式错误'); return; } // 尝试base64解码 $decoded = base64_decode($part, true); if ($decoded === false) { $this->addError($arg, 'JWT令牌格式错误'); return; } } } /** * 验证签名参数 * * @param array $params * @param string $arg * @return void */ public function validateSignatureParams(array $params, string $arg): void { $requiredParams = ['timestamp', 'nonce', 'signature']; foreach ($requiredParams as $param) { if (!isset($params[$param]) || empty($params[$param])) { $this->addError($arg, "缺少必需的签名参数: {$param}"); return; } } // 验证时间戳 $timestamp = $params['timestamp']; if (!is_numeric($timestamp)) { $this->addError($arg, '时间戳格式错误'); return; } // 检查时间戳是否在合理范围内(5分钟内) $currentTime = time(); $timeDiff = abs($currentTime - $timestamp); if ($timeDiff > 300) { // 5分钟 $this->addError($arg, '请求时间戳过期'); return; } // 验证随机数 $nonce = $params['nonce']; if (strlen($nonce) < 8) { $this->addError($arg, '随机数长度不足'); return; } // 验证签名格式 $signature = $params['signature']; if (strlen($signature) !== 64 || !ctype_xdigit($signature)) { $this->addError($arg, '签名格式错误'); return; } } /** * 验证IP地址格式 * * @param string $ip * @param string $arg * @return void */ public function validateIpAddress(string $ip, string $arg): void { if (empty($ip)) { $this->addError($arg, 'IP地址不能为空'); return; } // 验证IPv4或IPv6地址 if (!filter_var($ip, FILTER_VALIDATE_IP)) { $this->addError($arg, 'IP地址格式错误'); return; } } /** * 验证IP白名单格式 * * @param array $ipList * @param string $arg * @return void */ public function validateIpWhitelist(array $ipList, string $arg): void { if (empty($ipList)) { $this->addError($arg, 'IP白名单不能为空'); return; } foreach ($ipList as $index => $ip) { if (empty($ip)) { $this->addError($arg, "第" . ($index + 1) . "个IP地址不能为空"); continue; } // 支持CIDR格式 if (str_contains($ip, '/')) { if (!$this->validateCidr($ip)) { $this->addError($arg, "第" . ($index + 1) . "个IP地址CIDR格式错误: {$ip}"); } } else { // 支持通配符 if (str_contains($ip, '*')) { if (!$this->validateWildcardIp($ip)) { $this->addError($arg, "第" . ($index + 1) . "个IP地址通配符格式错误: {$ip}"); } } else { // 普通IP地址 if (!filter_var($ip, FILTER_VALIDATE_IP)) { $this->addError($arg, "第" . ($index + 1) . "个IP地址格式错误: {$ip}"); } } } } } /** * 验证CIDR格式 * * @param string $cidr * @return bool */ protected function validateCidr(string $cidr): bool { $parts = explode('/', $cidr); if (count($parts) !== 2) { return false; } [$ip, $mask] = $parts; // 验证IP地址 if (!filter_var($ip, FILTER_VALIDATE_IP)) { return false; } // 验证子网掩码 if (!is_numeric($mask)) { return false; } $mask = (int)$mask; if (filter_var($ip, FILTER_VALIDATE_IP, FILTER_FLAG_IPV4)) { // IPv4 return $mask >= 0 && $mask <= 32; } else { // IPv6 return $mask >= 0 && $mask <= 128; } } /** * 验证通配符IP格式 * * @param string $ip * @return bool */ protected function validateWildcardIp(string $ip): bool { // 将*替换为0进行验证 $testIp = str_replace('*', '0', $ip); return filter_var($testIp, FILTER_VALIDATE_IP) !== false; } /** * 验证频率限制配置 * * @param array $rateLimits * @param string $arg * @return void */ public function validateRateLimits(array $rateLimits, string $arg): void { $validTypes = [ 'requests_per_minute', 'requests_per_hour', 'requests_per_day', 'requests_per_week', 'requests_per_month' ]; foreach ($rateLimits as $type => $limit) { if (!in_array($type, $validTypes)) { $this->addError($arg, "无效的限制类型: {$type}"); continue; } if (!is_numeric($limit) || $limit < 0) { $this->addError($arg, "限制值必须是非负数: {$type}"); continue; } // 检查限制值的合理性 $maxLimits = [ 'requests_per_minute' => 1000, 'requests_per_hour' => 10000, 'requests_per_day' => 100000, 'requests_per_week' => 500000, 'requests_per_month' => 2000000, ]; if ($limit > $maxLimits[$type]) { $this->addError($arg, "限制值过大: {$type} 最大值为 {$maxLimits[$type]}"); } } } /** * 验证权限范围 * * @param array $scopes * @param string $arg * @return void */ public function validateScopes(array $scopes, string $arg): void { if (empty($scopes)) { $this->addError($arg, '权限范围不能为空'); return; } $validScopes = [ 'USER_READ', 'USER_WRITE', 'GAME_READ', 'GAME_WRITE', 'ITEM_READ', 'ITEM_WRITE', 'FUND_READ', 'FUND_WRITE', 'TRADE_READ', 'TRADE_WRITE', 'ADMIN_READ', 'ADMIN_WRITE', 'SYSTEM_READ', 'SYSTEM_WRITE', 'NOTIFICATION_READ', 'NOTIFICATION_WRITE', 'LOG_READ', '*', 'ADMIN' ]; foreach ($scopes as $scope) { if (!in_array($scope, $validScopes)) { $this->addError($arg, "无效的权限范围: {$scope}"); } } } }