PHP如何检测请求来自浏览器还是自动化脚本?
检测脚本请求并拦截的方法探讨
一、通过setCookie返回值判断的可行性
这种方法不可行,原因如下:
setCookie返回false的场景仅包括:HTTP头已提前输出(无法设置Cookie)、客户端(浏览器/脚本)禁用了Cookie。- 自动化脚本(如Python requests、PHP cURL)默认支持处理Cookie,调用
setCookie会返回true,无法区分脚本和正常浏览器。 - 若真实用户浏览器禁用Cookie,
setCookie会返回false,导致误拦截合法用户。
二、更可靠的前置拦截方法
以下方法可在返回完整HTML页面之前完成检测拦截,结合使用能大幅提高识别准确率:
1. JS挑战验证
服务端在首次请求时生成随机挑战值并存入Session,返回一段极简HTML触发JS,让JS自动携带挑战值发起二次请求,服务端验证通过后才返回目标页面。示例代码:
session_start(); $targetUrl = $_SERVER['REQUEST_URI']; // 验证挑战值 if (!isset($_SESSION['js_challenge']) || !isset($_GET['js_challenge']) || $_GET['js_challenge'] !== $_SESSION['js_challenge']) { $_SESSION['js_challenge'] = bin2hex(random_bytes(16)); // 返回JS跳转代码,触发二次请求 echo "<script>window.location.replace('{$targetUrl}?js_challenge={$_SESSION['js_challenge']}');</script>"; exit; } // 验证通过,继续处理目标页面逻辑
普通脚本因未执行JS,无法携带挑战值,会被拦截;无头浏览器虽能模拟JS,但可结合其他方法进一步识别。
2. 请求头特征校验
真实浏览器的请求头有固定顺序和必填项,脚本常出现异常:
- 检查请求头顺序:比如
Host必须是第一个头,User-Agent、Accept等需按标准顺序出现。 - 检查缺失的关键头:比如
Accept-Language、Accept-Encoding、Referer(合理场景下),缺失则直接拦截。 - 校验
User-Agent的真实性:避免过于简单或异常的UA字符串,可维护一个合法UA的白名单(需定期更新)。
3. 人机验证(CAPTCHA)
在返回目标页面之前,先要求用户完成滑动验证、字符识别等人机交互操作,服务端验证通过后才允许访问。这是目前对抗自动化脚本最有效的方法之一,能拦截绝大多数非无头脚本。
4. 请求频率与行为分析
- 限制同一IP的请求频率:短时间内多次请求同一页面,直接拦截。
- 检查Session的建立流程:真实用户会有正常的页面跳转轨迹(如从首页进入目标页),脚本常直接访问目标页,可通过Session记录访问路径,异常则拦截。
注意事项
没有100%完美的检测方法,无头浏览器可模拟几乎所有浏览器行为。实际应用中建议结合多种方法,提高脚本的绕过成本,同时避免过度拦截影响正常用户体验。
内容的提问来源于stack exchange,提问作者rolinger
相关产品推荐
相关产品推荐

