应自定义中间件继承 ThrottleRequests 并重写 resolveRequestSignature() 方法,使白名单 IP 返回固定键如 "throttle_bypass" 以绕过限流。

如何在 Laravel 中为特定 IP 设置 API 速率限制白名单
Laravel 默认的 throttle 中间件不支持直接配置 IP 白名单,必须通过自定义限流键($key)或重写限流逻辑来绕过。硬编码白名单或在中间件里做条件跳过是常见但易出错的做法。
- 不要直接修改
App\Http\Kernel中的throttle:60,1配置项来“加例外”,它不识别 IP 条件 - 真正生效的方式是:让白名单 IP 的请求生成一个永远不触发限流的限流键,例如固定为
"throttle_bypass" - 更稳妥的做法是自定义中间件,继承
Illuminate\Routing\Middleware\ThrottleRequests,重写resolveRequestSignature()方法
// app/Http/Middleware/ThrottleWithWhitelist.php
<?php <p>namespace App\Http\Middleware;<p>use Illuminate\Routing\Middleware\ThrottleRequests;
use Illuminate\Http\Request;</p><p>class ThrottleWithWhitelist extends ThrottleRequests
{
protected function resolveRequestSignature(Request $request): string
{
$ip = $request->ip();
$whitelist = config('throttle.whitelist', []);</p><pre class="brush:php;toolbar:false;"> if (in_array($ip, $whitelist)) {
return 'throttle_bypass_' . $ip; // 固定键,永不超限
}
return parent::resolveRequestSignature($request);
}
}
然后在 app/Http/Kernel.php 中注册该中间件,并在路由中使用:
protected $middlewareGroups = [ 'api' => [ ..., \App\Http\Middleware\ThrottleWithWhitelist::class . ':60,1' ] ];
Laravel throttle 中间件对 IPv4/v6 的兼容性问题
Laravel 9+ 默认调用 $request->ip(),它在 Nginx 反向代理下可能返回 127.0.0.1 而非真实客户端 IP,导致白名单失效。
- 确保已正确配置
TrustProxies中间件,且$proxies包含你的反代服务器 IP 段 - 检查
config/trustedproxy.php中的headers是否启用X-Forwarded-For - 若使用 Cloudflare,需额外在
TrustProxies中添加Illuminate\Http\Request::HEADER_X_FORWARDED_FOR并设置可信 IP 列表 - 测试方法:在控制器中打印
$request->ip()和$request->server('HTTP_X_FORWARDED_FOR')对比
为什么不能在路由闭包里用 if 判断跳过 throttle
有人尝试这样写:
Route::middleware(['throttle:60,1'])->group(function () {
Route::get('/api/data', function () { /* ... */ });
});
// 然后在闭包里加 if ($request->ip() === '1.2.3.4') { return ... }
这完全无效,因为 throttle 中间件在进入路由闭包前就已执行并计数。即使你在闭包里提前 return,限流计数器早已递增。
- 限流逻辑发生在中间件栈层级,不是路由执行时才检查
- 所有依赖「运行时跳过」的方案都不可靠,必须在限流键生成阶段干预
- 唯一安全时机是重写
resolveRequestSignature()或使用自定义存储驱动(如 Redis 键前缀隔离)
生产环境白名单配置建议
把白名单从代码移到配置,便于运维管理与环境隔离:
在 config/throttle.php 中添加:
return [
'whitelist' => explode(',', env('THROTTLE_WHITELIST', '127.0.0.1')),
];
再在 .env 中写:THROTTLE_WHITELIST=192.168.1.100,203.0.113.5
- 不要将白名单硬编码进中间件类,否则无法区分本地、测试、生产环境
- 注意
in_array()默认是严格比较,IPv6 地址字符串长度长,确保没多余空格 - 如果使用 Docker 或 Kubernetes,注意容器内获取的 IP 可能是 Pod IP,应以入口网关(如 Ingress Controller)上报的为准
IP 白名单真正难的不是写几行代码,而是确认你拿到的 IP 是谁、经过了几层代理、有没有被篡改——这些不厘清,限流键再巧妙也白搭。
大量免费API接口:立即使用
涵盖生活服务API、金融科技API、企业工商API、等相关的API接口服务。免费API接口可安全、合规地连接上下游,为数据API应用能力赋能!











