跳转到主内容
websoft网络软件专家 - 深耕网络技术,打造实用软件!

如何在Laravel中为API请求设置速率限制(Rate Limiting)? (Throttle中间件)

Laravel API 速率限制需显式配置 throttle 中间件,如 throttle:60,1;默认按 IP 限流,登录用户需确保 auth:sanctum 在 throttle 前执行;自定义策略应于 RouteServiceProvider 中定义并指定 by() 键;生产环境必须使用 Redis 缓存驱动。 直接在 Laravel 中用
throttle
中间件就能实现 API 速率限制,无需额外包。关键在于 路由 定义时的参数组合和自定义限流策略的时机。 如何在 API 路由中启用 throttle 中间件 Laravel 默认已为
api
路由组注册了
throttle:api
,但这个策略实际是空的(Laravel 9+),必须手动配置或替换。最常用做法是显式指定中间件参数:
throttle:60,1
表示每分钟最多 60 次请求
throttle:100,5
表示每 5 分钟最多 100 次 参数顺序固定:请求数量,时间窗口(单位:分钟) 该中间件默认按客户端 IP 限流;如需按用户 ID 或 API token 区分,需自定义 为什么匿名用户被限流而登录用户没效果? 因为默认
throttle
实现使用
$request->ip()
作为 key 基础,对所有未认证请求一视同仁。而登录用户若走的是
api
guard 且未在中间件中显式切换识别逻辑,仍可能 fallback 到 IP —— 尤其当你的认证是通过
Authorization: Bearer xxx
但未启用
EnsureTokenIsValid
类中间件时。 确保 API 认证中间件(如
auth:sanctum
)在
throttle
之前执行 否则
Auth::id()
取不到值,限流 key 退化为 IP 正确顺序示例:
middleware(['auth:sanctum', 'throttle:30,1'])
如何按用户 ID 或 API token 限流(而非 IP) 需要重写限流 key 的生成逻辑。Laravel 允许在
app/Providers/RouteServiceProvider.php
的
configureRateLimiting
方法中注册自定义策略: PHP 8.5.5 PHP 8.5.5 是 PHP 8.5 分支的维护更新版本。该版本延续了“小步快跑”的迭代逻辑,通过深度错误修复、底层性能微调以及安全加固,旨在为开发者提供一个更健壮、更高效的运行环境。该版本严格遵守语义化版本规范,不包含破坏性变更。 下载
use Illuminate\Cache\RateLimiting\Limit; use Illuminate\Http\Request; RateLimiter::for('api_by_user', function (Request $request) { return $request->user() ? Limit::perMinute(60)->by($request->user()->id) : Limit::perMinute(10)->by($request->ip()); });
然后在路由中使用:
middleware('throttle:api_by_user')
。注意:
by()
的值必须是字符串,且不能含特殊字符;若用 token,建议取
hash_hmac('sha256', $token, config('app.key'))
再截断。 常见错误:429 响应体不包含 Retry-After 或 X-RateLimit 头 这是因你用了非标准响应格式(比如全局返回 JSON 的异常 处理器 覆盖了 Laravel 原生
ThrottleRequests
的响应逻辑)。原生中间件会在响应头中自动添加:
X-RateLimit-Limit
:窗口内最大请求数
X-RateLimit-Remaining
:剩余可请求数
Retry-After
:秒级等待时间(仅当超出时) 若这些头缺失,检查是否在
App\Exceptions\Handler.php
中误捕获了
ThrottleRequestsException
并返回了无头响应 真正容易被忽略的是:缓存驱动必须支持原子计数(如 Redis),否则
file
或
database
缓存在高并发下会漏限流。生产环境务必确认
CACHE_DRIVER=redis
且连接正常。

相关文章