| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176 |
- <?php
- namespace App\Module\OpenAPI\Validators;
- use UCore\Validator;
- /**
- * 频率限制配置验证器
- */
- class RateLimitConfigValidator extends Validator
- {
- /**
- * 验证频率限制配置是否有效
- *
- * @param mixed $value 频率限制配置数组
- * @param array $data 验证数据
- * @return bool 验证是否通过
- */
- public function validate(mixed $value, array $data): bool
- {
- // 从 args 获取参数
- $processedKey = $this->args[0] ?? 'processedRateLimits';
- if (empty($value)) {
- // 使用默认配置
- $value = $this->getDefaultRateLimits();
- }
- if (!is_array($value)) {
- $this->addError('频率限制配置必须是数组格式');
- return false;
- }
- $processedLimits = [];
- $validTypes = $this->getValidLimitTypes();
- foreach ($value as $type => $limit) {
- // 验证限制类型
- if (!in_array($type, $validTypes)) {
- $this->addError("无效的限制类型: {$type}");
- return false;
- }
- // 验证限制值
- if (!$this->validateLimitValue($type, $limit)) {
- return false;
- }
- $processedLimits[$type] = (int)$limit;
- }
- // 验证限制值的合理性
- if (!$this->validateLimitReasonableness($processedLimits)) {
- return false;
- }
- // 将处理后的配置保存到验证对象中
- $this->validation->$processedKey = $processedLimits;
- return true;
- }
- /**
- * 获取有效的限制类型
- *
- * @return array
- */
- protected function getValidLimitTypes(): array
- {
- return [
- 'requests_per_minute',
- 'requests_per_hour',
- 'requests_per_day',
- 'requests_per_week',
- 'requests_per_month'
- ];
- }
- /**
- * 获取默认频率限制配置
- *
- * @return array
- */
- protected function getDefaultRateLimits(): array
- {
- return [
- 'requests_per_minute' => 60,
- 'requests_per_hour' => 1000,
- 'requests_per_day' => 10000,
- 'requests_per_week' => 50000,
- 'requests_per_month' => 200000,
- ];
- }
- /**
- * 验证限制值
- *
- * @param string $type
- * @param mixed $limit
- * @return bool
- */
- protected function validateLimitValue(string $type, mixed $limit): bool
- {
- if (!is_numeric($limit)) {
- $this->addError("限制值必须是数字: {$type}");
- return false;
- }
- $limit = (int)$limit;
- if ($limit < 0) {
- $this->addError("限制值不能为负数: {$type}");
- return false;
- }
- // 验证最大限制值
- $maxLimits = [
- 'requests_per_minute' => 10000,
- 'requests_per_hour' => 100000,
- 'requests_per_day' => 1000000,
- 'requests_per_week' => 5000000,
- 'requests_per_month' => 20000000,
- ];
- if (isset($maxLimits[$type]) && $limit > $maxLimits[$type]) {
- $this->addError("限制值过大: {$type} 最大值为 {$maxLimits[$type]}");
- return false;
- }
- return true;
- }
- /**
- * 验证限制值的合理性
- *
- * @param array $limits
- * @return bool
- */
- protected function validateLimitReasonableness(array $limits): bool
- {
- // 验证时间单位之间的合理性
- $timeUnits = [
- 'requests_per_minute' => 1,
- 'requests_per_hour' => 60,
- 'requests_per_day' => 1440,
- 'requests_per_week' => 10080,
- 'requests_per_month' => 43200, // 30天
- ];
- foreach ($limits as $type => $limit) {
- if (!isset($timeUnits[$type])) {
- continue;
- }
- $perMinute = $limit / $timeUnits[$type];
- // 检查是否有更短时间单位的限制
- foreach ($timeUnits as $shorterType => $shorterMultiplier) {
- if ($shorterMultiplier >= $timeUnits[$type]) {
- continue;
- }
- if (isset($limits[$shorterType])) {
- $shorterPerMinute = $limits[$shorterType] / $shorterMultiplier;
-
- if ($perMinute > $shorterPerMinute) {
- $this->addError("限制配置不合理: {$type} 的平均速率不能超过 {$shorterType}");
- return false;
- }
- }
- }
- }
- return true;
- }
- }
|