laravel无法单靠中间件彻底禁止爬虫,需分层设防:识别ua等特征→用redis支撑的throttle限流压制→权限隔离→响应头干扰;必须改造默认限流键、禁用array缓存驱动、结合nginx前置拦截。

直接靠中间件“禁止爬虫”不现实,Laravel 没有内置的“反爬虫中间件”,但可以通过组合配置和自定义中间件,有效识别、限制或拦截可疑爬虫行为。关键不是一刀切封禁,而是分层设防:识别特征 → 限流压制 → 权限隔离 → 响应干扰。
识别并拦截明显非浏览器请求
很多爬虫不带标准浏览器 User-Agent,或缺失关键头信息(如 Accept、Accept-Language)。可写一个轻量中间件做初步过滤:
- 检查 User-Agent 是否为空、过于简短,或匹配已知爬虫关键词(如 'bot'、'crawl'、'spider'、'curl'、'httpclient')
- 验证是否携带 Accept: text/html 或常见浏览器 MIME 类型,纯 API 爬虫常忽略此头
- 拒绝 没有 Referer 或 Referer 为 null/空 的敏感页面请求(如登录页、后台入口),但注意 SPA 场景下 Referer 可能缺失,需结合上下文判断
- 用
abort_if()快速终止:例如abort_if($request->header('User-Agent') === null || Str::contains(strtolower($request->userAgent()), ['bot', 'crawl']), 403);
用 throttle 中间件压制高频爬取
这是最实用、见效最快的手段。但默认按 IP 限流在现代网络环境下基本失效,必须改造:
- 确保
CACHE_DRIVER=redis,否则多进程下计数器不同步,限流形同虚设 - 避免直接写
throttle:10,1,改用命名限流器 + 自定义 key:在App\Providers\RouteServiceProvider的boot()中注册 - 对公开接口(如搜索、列表页),用设备标识代替 IP:
RateLimiter::for('public', function (Request $request) { return Limit::perMinute(5)->by($request->header('X-Device-ID') ?: $request->ip()); }); - 对登录、注册等高风险路由,强制绑定用户或手机号:
->middleware('throttle:3,1,by=id'),前提是已通过auth:sanctum认证
配合安全响应头降低爬取价值
即使爬虫进来了,也能让它难解析、难复用、难嵌入:
- 添加 X-Robots-Tag: noindex, nofollow 响应头,明确告知搜索引擎不要收录该页面(对 SEO 页面慎用)
- 设置 Content-Security-Policy 限制 script/style 加载源,阻止爬虫注入恶意 JS 提取数据
- 对管理后台、用户中心等区域,返回头中加 X-Frame-Options: DENY,防止被嵌入 iframe 进行点击劫持或隐蔽爬取
- 敏感接口返回 JSON 时,避免返回完整 HTML 错误页;统一用
response()->json(['error' => 'Forbidden'], 403),减少结构化信息暴露
补充策略:不依赖中间件但必须同步做
中间件只是链路一环,真正防住爬虫还需配套动作:
- 在网站根目录放好
robots.txt,明确禁止爬取/admin/、/api/、/storage/等路径 - 静态资源(CSS/JS/图片)走 CDN,并在 CDN 层配置 UA 黑名单或频率规则,减轻 Laravel 应用层压力
- 关键表单(如登录、评论)启用验证码(如 reCAPTCHA v3),服务端验证 token 后再放行,中间件里调用验证逻辑即可
- 定期查看日志,提取高频访问的 UA 和 IP,加入临时黑名单中间件或 Nginx 配置











