Laravel怎么开启请求频率限制 _ Laravel Throttle限流配置方法【技巧】

1次阅读

throttlerequests中间件默认启用但仅对登录注册等内置路由生效,自定义路由需手动添加;须确认kernel.php中已注册且缓存驱动为redis、认证中间件前置以确保按用户id限流。

Laravel怎么开启请求频率限制 _ Laravel Throttle限流配置方法【技巧】

ThrottleRequests 中间件怎么启用

默认就开着,但只对登录、注册等内置路由生效。想给自定义路由限流,得手动加中间件。

常见错误是直接在 routes/web.php 里写 ->middleware('throttle:60,1') 却没确认该中间件是否已注册——laravel 从 5.2 起已预装,但如果你删过 app/http/Kernel.php 里的 ThrottleRequests::class,就会静默失效。

  • 检查 app/Http/Kernel.php$middlewareGroups['web']$routeMiddleware 里有没有 'throttle' => IlluminateRoutingMiddlewareThrottleRequests::class
  • 在路由分组中使用: Route::middleware('throttle:10,1')->group(...),其中 10 是次数,1 是分钟(单位固定为分钟)
  • 不要在 API 路由里误用 web 组的 throttle;API 应走 api 中间件组,并确保 throttle 已映射到该组

怎么按用户 ID 或 IP 区分限流粒度

默认 throttle 基于 IP,但登录用户应按 user.id 限流,否则共享 IP 的用户会互相干扰。

关键在 ThrottleRequests 构造逻辑:它调用 resolveRequestSignature() 获取“签名”,这个签名决定谁和谁算同一组。默认实现优先取 $request->user()?->id,没登录才 fallback 到 IP。

  • 确保路由绑定了 auth 中间件,否则 $request->user()NULL,退化成 IP 限流
  • 如果用 API Token 认证(如 Sanctum),需确认 auth:sanctum 正确执行,否则仍按 IP 算
  • 自定义签名?重写中间件或继承 ThrottleRequests,但多数情况只需保证认证中间件前置即可

缓存驱动影响限流行为

限流计数器存在缓存里,用的是 Laravel 默认缓存驱动。如果用的是 fileArray 驱动,多机部署时完全不生效——每台机器各自计数。

错误现象:本地开发一切正常,上线后限流形同虚设;或者 nginx 后面挂了多个 PHP-FPM 实例,用户刷几次就解封。

  • 生产必须用支持原子操作的缓存:推荐 rediscache.driver=redis),memcached 次之
  • Redis 要求版本 ≥ 2.6.12(因依赖 INCR + EXPIRE 原子组合),低版本可能漏计数
  • 别在 .env 里配 CACHE_DRIVER=array 上生产,这个驱动连跨请求都不共享,仅适合测试

自定义响应格式和状态码

触发限流时默认返回 429 状态码和纯文本 Too Many Requests,前端难处理。要改响应,不能改中间件源码,得通过异常渲染拦截。

Laravel 把 ThrottleRequests 抛出的异常统一转为 ThrottleRequestsException,最终由 AppExceptionsHandler::render() 处理。

  • app/Exceptions/Handler.phprender() 方法里加判断:if ($exception instanceof IlluminateHttpExceptionsThrottleRequestsException)
  • 返回 json 响应:return response()->json(['message' => '请求太频繁,请稍后再试'], 429)
  • 注意:别漏掉 use IlluminateHttpExceptionsThrottleRequestsException;,否则类名解析失败,异常直接透出

真正容易被忽略的是缓存驱动和认证中间件顺序——这两个点不出错时一切丝滑,一出错就是线上限流完全失效,且日志里几乎不报错。

text=ZqhQzanResources