You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Laravel限流:不同请求次数设不同延迟及IP封禁问题排查

Laravel限流中间件问题排查与修复

核心问题分析

你的代码存在三个关键错误:

  1. 尝试次数判断时机错误:在调用hit()前获取attempts(),此时的次数是历史请求数,导致冷却时间逻辑完全不匹配需求(比如第一次请求时attempts()返回0,错误进入10分钟冷却分支)。
  2. 限流逻辑偏差:tooManyAttempts()是判断"请求次数超过阈值",但你的需求是"每次请求后,下一次必须等待对应时间",应该检查是否处于冷却期而非次数超限。
  3. 未实现高频封禁规则:原代码完全没处理"1分钟10次请求封禁3小时"的需求。

修复后的完整代码

public function handle($request, Closure $next)
{
    $limiter = app(RateLimiter::class);
    $ip = $request->ip();
    $progressKey = sha1($ip . '_progress'); // 递进延迟的独立限流标识
    $banKey = sha1($ip . '_ban'); // 高频封禁的独立限流标识

    // 先处理高频封禁规则:1分钟内10次请求封禁3小时
    if ($limiter->tooManyAttempts($banKey, 10)) {
        $limiter->hit($banKey, 3 * 60); // 延长封禁时间至3小时(单位:分钟)
        return response('Your IP has been banned for 3 hours due to excessive requests.', 429);
    }
    $limiter->hit($banKey, 1); // 记录本次请求,冷却时间1分钟

    // 处理递进延迟规则
    $currentAttempts = $limiter->attempts($progressKey);
    // 根据当前请求次数设置下一次的冷却时间(单位:秒)
    if ($currentAttempts === 0) {
        $coolDownSeconds = 30;    // 第1次请求后,下一次需等30秒
    } elseif ($currentAttempts === 1) {
        $coolDownSeconds = 60;    // 第2次请求后,下一次需等60秒
    } else {
        $coolDownSeconds = 120;   // 第3次及以后请求后,下一次需等120秒
    }

    // 检查是否处于冷却期
    if ($limiter->availableIn($progressKey) > 0) {
        $retryAfter = $limiter->availableIn($progressKey);
        return response("Please wait {$retryAfter} seconds before your next request.", 429);
    }

    // 处理请求并设置冷却时间(hit的第二个参数是分钟,需转换单位)
    $limiter->hit($progressKey, $coolDownSeconds / 60);
    $response = $next($request);

    return $response;
}

关键修改说明

  1. 拆分限流标识:用两个独立的key分别处理递进延迟和高频封禁,避免规则互相干扰。
  2. 高频封禁逻辑:
    • 用$banKey统计1分钟内的请求次数,阈值设为10次。
    • 达到阈值后,直接返回封禁提示并设置3小时冷却,确保封禁期间无法发起请求。
  3. 递进延迟逻辑:
    • 根据当前已有的请求次数,动态设置下一次请求的冷却时间。
    • 用availableIn($key)检查是否处于冷却期,只要返回值大于0,就拒绝当前请求。
  4. 修正时间单位:Laravel的hit()方法第二个参数是分钟,所以需要将秒数转换为分钟传入(比如30秒=0.5分钟)。

内容的提问来源于stack exchange,提问作者Mimi

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.25 09:47:06