ThinkPHP中应通过中间件用配置文件白名单+stripos校验User-Agent实现轻量爬虫识别,仅作快速放行而非安全屏障;空UA或含python-requests等异常UA需标记限流,验证码须结合JS行为、Cookie、IP频次动态触发。

ThinkPHP 里怎么用 User-Agent 做基础爬虫识别
靠 User-Agent 字符串本身做“白名单”是脆弱的,但它是第一道轻量过滤——不是为了拦住所有爬虫,而是快速放过已知可信客户端(比如自家 App、合作方接口),同时标记出明显异常流量(如空 UA、含 python-requests 却走 Web 路由)。
ThinkPHP 6+ 中,request()->header('user-agent') 可取值;5.x 则用 input('server.HTTP_USER_AGENT')。别直接在控制器里硬编码判断逻辑,应抽到中间件或行为钩子中。
- 白名单建议存在配置文件(如
app/extra/spider.php),而非数据库——避免每次请求都查库 - 匹配用
stripos()而非全等,因为 UA 可能带版本号、平台信息等变体 - 注意移动端 UA(如
Mobile Safari)和桌面端(Chrome)要分开看,别把微信内置浏览器误标为爬虫 - 空
User-Agent或纯数字/乱码字符串(如123456)大概率是恶意扫描器,可直接halt()或记录后限流
为什么不能只靠 User-Agent 就放行或拦截
因为 User-Agent 完全可伪造,主流爬虫框架(Scrapy、Playwright、Requests)默认就随机 UA,甚至能完美复刻 Chrome 最新 UA。你加了白名单,攻击者只要照抄一行字符串就能绕过。
典型翻车场景:curl -H "User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36" 直接打穿你的“UA 白名单”,连验证码都不触发。
立即学习“PHP免费学习笔记(深入)”;
- 真实业务中,UA 只适合做“快速放行”(如内部系统调用),绝不该用于“放行即信任”
- 如果某接口被高频调用且 UA 合法,但无 Cookie、无 Referer、无 JS 执行痕迹,大概率仍是爬虫
- TP 的
think\facade\Request不会自动校验 UA 真实性,它只是原样返回 header 值,别高估它的防护能力
验证码该在什么时候触发:别等用户点提交才弹
人机对抗的关键不是“加不加验证码”,而是“在哪个环节、对谁加”。ThinkPHP 自带的 captcha 扩展只提供生成和验证函数,不决定触发时机——这个决策必须由你控制。
推荐策略:对高风险动作(如登录、注册、批量导出)做前置风险评分,而不是固定路径强制弹验证码。
- 首次访问页面时,通过 JS 注入一个隐藏字段(如
_ts),记录页面加载到点击的毫秒差;小于 800ms 的基本是脚本提交,直接拦截 - 检查
request()->cookie('thinkphp_token')是否存在且未过期——真用户有 Cookie,多数爬虫没耐心维持会话 - 结合 IP 请求频次(可用
think\Cache记录ip:login:count)和 UA 变化频率,双指标超阈值再触发captcha() - 验证码图片地址别写死,用
url('captcha')动态生成,并确保路由未被 CDN 缓存(否则多个用户看到同一张图)
TP 验证码常见报错与绕过陷阱
captcha/check 返回 false 是最常遇到的问题,但原因五花八门,调试时别只盯着前端传参。
-
session_start()失败会导致验证码 session 写入失败——确认session.auto_start = 0,且 TP 的session配置项(如type、prefix)与实际环境匹配 - 前后端域名不一致(如前端用
https://a.com,后端接口在https://api.b.com)时,Cookie 默认不携带,captcha/check拿不到服务端存的验证码值 - 验证码图片正常显示但校验总失败?检查是否启用了
ob_start()或输出了 BOM,导致 session 写入前已有输出 - 别在验证码校验通过后立刻清 session——有些业务需要连续操作(如多步表单),清太早会导致第二步校验失败
真正难防的不是手动填错验证码的人,而是用 OCR + 代理池轮询的自动化流程。UA 白名单和验证码只是成本门槛,不是安全边界。别把规则写死在代码里,留个开关配置项,方便灰度和紧急关闭。


















