发布于2026-07-06 阅读(0)
扫一扫,手机访问
先说几个核心判断:单纯靠 User-Agent 白名单防爬虫,在 ThinkPHP 这类框架里基本等于“形同虚设”。UA 这玩意儿,谁都能伪造,拿来当安全屏障,敌人只要照抄几个合法字符串就能轻松绕过。它的正确用法,其实是作为第一道快速过滤——放行那些明显可信的客户端,或者标记一下异常流量,比如 User-Agent 字段是空的、纯数字的、或者里面直接挂着 python-requests、curl 这些标识的请求。仅此而已。
真正的防御链条,需要串起中间件统一过滤、行为特征分析、以及动态验证码触发机制,同时别忘了把 CSRF 令牌这套防护老老实实加上。
很多开发者习惯在控制器里顺手写一句 if (stripos($ua, 'Chrome') !== false) 之类的判断。这不是个好习惯。控制器是处理业务逻辑的地方,不是写流量筛子的。代码复用难、后续升级排查都是坑。
正确的做法是写一个中间件,比如 app/middleware/UserAgentFilter.php,在 handle() 方法里统一处理。有几个细节值得注意:
request()->header('user-agent'),这是 ThinkPHP 6+ 推荐的方式。别直接去读 $_SERVER['HTTP_USER_AGENT'],否则在 Swoole 或 FastCGI 模式下,这个变量可能为空,坑你没商量。app/extra/spider.php 这类配置文件中,比如 return ['Mobile Safari', 'Chrome', 'WeChat'];。千万别在中间件里硬编码,也别去查数据库——首字节响应时间经不起这种折腾。stripos(),而不是 == 或者正则全匹配。合法的 User-Agent 变体太多了,iPhone 和 iPad 的 UA 除了平台字段不同,其他几乎一样,你很难写个精确匹配覆盖所有情况。123456),或者 UA 里带着 curl、httpie、python-requests 的请求,建议记录日志并触发限流。但别一刀切直接用 halt() 打死,误伤正常用户的代价可能更大。说白了,User-Agent 就是一个 HTTP 头,客户端想怎么写就怎么写。Scrapy、Playwright、Requests 这些工具,默认就会随机生成 UA,甚至能完美复刻最新版 Chrome 的 User-Agent。你加的白名单,敌人只要照抄一行字符串就能绕过。
curl -H "User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36"。瞧瞧,你的“UA 白名单”是不是直接被打穿了?Cookie、没有 Referer、X-Requested-With 字段为空、或者缺少 JS 行为相关的字段。举个例子,一个请求从页面加载到点击某个按钮的间隔,如果小于 800 毫秒,基本可以断定是脚本模拟的。request()->cookie('thinkphp_token') 是否存在且未过期。真实的用户访问,通常会带着会话标识;而绝大多数爬虫,连维护一个 Cookie jar 都懒得做。人机对抗这件事,难点不是“要不要加验证码”,而是“在哪个环节加、对谁加”。ThinkPHP 自带的 captcha 扩展,只提供了生成和验证的函数,它不会替你决定什么时候该弹验证码。
可行的思路是这样:
_ts(时间戳)。服务端收到请求后,比对 request()->post('_ts') 和当前时间的差值。如果小于 800 毫秒,基本可以判定是脚本在提交。表单防恶意提交,光指望 UA 或者 Referer 是不靠谱的。ThinkPHP 的 CSRF 防护依赖令牌机制,而且必须显式启用,效果才会到位。
@csrf 指令,它会自动生成 。这是基础操作。
说到底,UA 白名单一旦写死,反而容易成为攻击者的路标——他们只需要绕开那几个关键词就行。而验证码,如果只在提交时刻才校验,等于你把门锁装在了用户已经进门之后。真正的防御,是一套组合拳:从请求进门的第一道过滤,到行为层面的持续分析,再到关键环节的动态验证。缺一环,效果都会大打折扣。
售后无忧
立即购买>office旗舰店
售后无忧
立即购买>office旗舰店
售后无忧
立即购买>office旗舰店
售后无忧
立即购买>office旗舰店
正版软件
正版软件
正版软件
正版软件
正版软件
1
2
3
7
8