laravel防爬虫需用redis驱动的throttle中间件,限流键应基于x-device-id等业务标识而非ip,并在routeserviceprovider中按角色+设备定义分层策略,统一返回json格式429响应。

直接用 Laravel 内置的 throttle 中间件就能防基础爬虫,但默认按 IP 限流在 CDN、NAT 或代理环境下极易失效——关键不是加不加中间件,而是限流键(key)是否真实反映“独立访问者”。
必须用 Redis 驱动,不能用 array 或 file
限流依赖缓存记录计数,多进程下若用 CACHE_DRIVER=array,各 worker 之间数据不共享,限流完全失效。
- 检查
.env:确保CACHE_DRIVER=redis(或memcached) - 验证 Redis 连通性:运行
php artisan tinker后执行cache()->store('redis')->put('test', 'ok', 10),能写入才说明可用 - 不要在
web路由组里用 throttle,因为 web 默认不启用 Redis 缓存驱动
别只靠 IP,优先用业务标识做限流 key
真实用户常共用公网 IP(如公司出口、校园网、CDN 回源),而爬虫可轻易换 IP。用业务层唯一标识才能精准约束。
- App 客户端传
X-Device-ID,后端取值后过滤特殊字符:preg_replace('/[^a-zA-Z0-9_\-]/', '', $request->header('X-Device-ID')) - 小程序用
X-OpenID,后台管理接口强制带X-Tenant-ID - 有 API Key 的场景,建议哈希处理:
hash_hmac('sha256', $token, config('app.key')),避免明文 key 污染 Redis key 空间 - by() 的返回值严禁含冒号、点号、斜杠或空格,否则 Redis key 损坏,计数器永久错乱
注册命名策略,按角色+设备双维度限流
在 app/Providers/RouteServiceProvider.php 的 configureRateLimiting() 方法中定义:
- 先识别高危请求(如登录、密码重置),单独设严规:
if ($request->is('api/login')) return Limit::perMinute(3)->by($request->ip()); - 再判断用户身份:管理员 → VIP → 普通用户 → 游客,逐级回落,顺序不能颠倒
- 游客限流必须防 CDN 污染:
str_replace([':', '.'], '-', $request->ip())再作为 key - 策略名要统一,比如叫
role_and_device,路由中写middleware('throttle:role_and_device')
统一返回 JSON 格式 429 响应
默认限流响应是 HTML 页面,前端难解析。建议自定义中间件继承 ThrottleRequests,重写 handle 方法:
- 检测到状态码为 429 时,返回标准 JSON:
response()->json(['error' => 'Too many requests', 'retry_after' => $seconds], 429) - 保留原响应头(如
X-RateLimit-Limit、Retry-After),方便前端做倒计时重试 - 避免全局异常处理器覆盖 ThrottleRequests 的原生响应逻辑
大量免费API接口:立即使用
涵盖生活服务API、金融科技API、企业工商API、等相关的API接口服务。免费API接口可安全、合规地连接上下游,为数据API应用能力赋能!











