JS 防护流派全景解析:四种技术路线与它们的对抗成本
JS 防护流派全景解析:四种技术路线与它们的对抗成本
同样是「前端 JS 防护」,瑞数、同盾、极验、Cloudflare 走的是完全不同的路。
把它们的原理摊开对比,会发现真正决定逆向成本的,往往不是算法有多复杂,而是「防护目标」定在哪里。
引言:为什么会有「流派」
前端防护的本质是在做一件事:在客户端不可信的前提下,尽量判断请求是不是人发出来的。
但「判断」这件事可以有很多切入点:
- 判断发起请求的代码对不对(执行流校验)
- 判断发起请求的环境像不像真人设备(设备指纹)
- 判断发起请求的动作像不像真人操作(行为轨迹)
- 判断这次访问的整体信誉够不够(边缘挑战)
四个切入点,长出了四类产品,也对应四种完全不同的对抗难度。很多人把它们的难度混为一谈,实际上差距非常大。
流派一:动态执行流(瑞数 BotGate / 部分顶象)
原理
这是国内最「硬核」的一路。核心思路不是校验请求参数,而是校验执行请求的那段代码本身。
1~5 代:动态混淆 + eval
每次页面加载时,服务端下发一段 JS,其中:
- 字符字典顺序每次随机(同一个函数,今天叫
a.b(c),明天叫x.y(z)) - 变量名、函数名全是随机生成的短标识符
- 控制流被打散重排,插入大量无效分支
- 关键逻辑(参数生成、Cookie 写入)被拆成碎片,运行时拼接
每次加载都不一样,意味着你无法通过「找特征码」来定位逻辑——上一次抓到的函数结构,下一次就找不到了。所有碎片最终被 eval 或 Function 还原执行,产出签名参数和 Cookie。
6 代 + VMP 版:自定义字节码
再往上走一层,不再给你可读的 JS。原始逻辑被编译成自定义 opcode 字节码,页面上只有一段解释器代码,运行时把字节码喂给解释器执行。这时候静态分析基本失效——你面对的不是 JS,是一门只有它自己认识的小语言。
这一派的强度在哪
它防的不是「你会不会抓包」,而是「你能不能稳定复现出一模一样的参数」。
- 静态分析:基本无效(尤其 VMP 版)
- 动态调试:可以,但要对抗反调试(debugger 陷阱、
toString校验、时间差检测、格式化检测) - 稳定性:极高。因为「代码不可预测」+「请求一次一密」,任何硬编码方案都会在换版本时失效
识别特征
- 页面首屏 HTML 里就带着一段极长的混淆 JS
- 首次访问返回 412 / 521 之类的状态码,并
Set-Cookie一个看起来随机的短 Cookie - 同一 URL 连续刷新几次,返回的 JS 内容完全不同
- 全局搜索能看到
eval、Function、大数组下标访问密集
顺带一提:这一派的「强度」在纯混淆类里是最高的,但放到整个谱系里,它仍然只挡静态分析这一件事——它不判断环境像不像人,也不判断行为像不像人。所以单靠它,在有完整浏览器环境的情况下是可以被绕过的,只是成本高。
流派二:设备指纹 + 风控打分(同盾、数美、顶象、部分腾讯)
原理
这一路的哲学完全不同:不硬拦,只打分。
页面加载时注入一段采集脚本,尽可能多地收集环境特征:
| 维度 | 采集内容 |
|---|---|
| 图形栈 | Canvas 渲染哈希、WebGL 的 vendor/renderer/参数、图像解码差异 |
| 音频栈 | AudioContext 的波形指纹 |
| 字体 | 已安装字体列表、字体度量差异 |
| 时区/语言 | 时区偏移、语言列表、Date 精度 |
| 硬件 | CPU 核数、内存容量、屏幕分辨率/色深、设备像素比 |
| 传感器 | 陀螺仪、加速度计是否存在及数值 |
| 网络 | 出口 IP、IP 归属、代理特征 |
| 行为 | 鼠标轨迹、键盘节奏、页面停留、滚动模式 |
这些特征组合成一个 deviceId(或 token),随业务请求一起上送。后端用模型打分,输出一个风险等级:
- 高风险 → 直接拒绝 / 强制验证码
- 中风险 → 降权、限频、加二次校验
- 低风险 → 放行
对抗难点在哪
关键点:难点不在「解算法」,而在「环境一致性」。
它的加密算法通常并不复杂(甚至不加密,就是明文 JSON + 简单签名),你很快就能把 deviceId 的生成逻辑扒出来。但问题是——
你补出来的环境,只要有一个维度跟真实设备不一致,分数就上不去。
比如:Canvas 哈希对不上、WebGL 拿不到真实 GPU 参数、navigator 属性是补出来的静态值、时区跟着服务器而不是用户、鼠标轨迹是匀速直线。任何一项露馅,后端不一定立刻拒绝,而是把你丢进「可疑池」——表现就是请求能通,但一直弹验证码,或者数据被降级返回。
这种「不明确报错、只默默降权」的设计,是这一派最难受的地方:你很难判断自己到底是哪里错了。
识别特征
- 页面里有采集 Canvas / WebGL / AudioContext 的代码
- 请求头或参数里带一个长字符串 token,且每次会话固定、换环境会变
- 同一个接口,换 IP / 换浏览器就要求验证码
- 返回内容「看起来正常但字段不全」,或频繁触发滑块
流派三:行为验证码流(极验、网易易盾、腾讯天御)
原理
这一派把判断点放在具体动作上,形态是滑块、点选、无感验证。
以滑块为例,流程是:
- 前端向服务端申请挑战,拿到背景图、缺口位置、以及一个会话 ID
- 用户拖动滑块,前端采集全过程数据:每个采样点的坐标、时间戳、按下/抬起时刻、加速度变化
- 这些轨迹数据被加密成
w、validate之类的参数,连同会话 ID 一起上送 - 后端用轨迹模型判定:是不是机器生成的
模型看的不是「终点对不对」,而是过程像不像人:
- 起步有加速段,中段匀速,末段减速微调(真人特征)
- 有轻微的回拉、抖动、Y 轴漂移
- 采样间隔不均匀
- 总耗时在合理区间(太快 = 脚本,太慢 = 可疑)
对抗难点在哪
逆向通常是「轨迹模拟」,而不是纯算法还原。
算法层面:w 参数的加密逻辑经常是 RSA / AES 组合,扒出来不算特别难,但每次版本升级都可能变。
真正的难点是轨迹的真实性。用贝塞尔曲线 + 抖动噪声能过一部分老版本,但新版模型会检测:
- 轨迹点的采样率是否与真实事件循环一致
- 坐标是否来自真实
mousemove(而不是合成事件) - 多设备下的轨迹分布是否落在合理人群范围内
外加设备指纹交叉校验(极验自己也做指纹),所以纯算法 + 假轨迹这条路越来越窄。
识别特征
- 页面出现明显的验证码组件(
gt.js、yidun、tcaptcha之类) - 请求里带
w、gt、challenge、validate等参数 - 无感模式下:正常访问无感,一旦被判定可疑就弹滑块
流派四:边缘挑战流(Cloudflare、Akamai、部分 CDN WAF)
原理
这一派在网络边缘做判断,业务服务器根本不参与。核心是三个手段叠加:
1. JS Challenge
首次访问时,边缘节点不返回真实内容,而是返回一个中间页,里面是一段 JS。这段 JS 在浏览器里做几件事:
- 跑一段计算(早期是简单的数学题,现在有更复杂的 PoW)
- 采集少量环境特征
- 把结果连同边缘节点下发的 token 一起提交
- 校验通过后,边缘节点下发
cf_clearanceCookie
之后带着这个 Cookie 的请求才被放行到源站。
2. Turnstile(无感验证)
Cloudflare 的托管挑战方案。不弹可见验证码,而是后台静默跑一段检测(环境 + 行为 + 信誉),给出通过/不通过。对真人几乎无感,对自动化环境则大概率卡住。
3. IP 信誉
这是最容易被忽略、也最容易被低估的一层。Cloudflare 手里有全网级别的流量数据:
- 这个 IP 段历史上有没有大量异常请求
- 这个 IP 是不是机房/云厂商/代理出口
- 这个 ASN 的整体信誉
- TLS 指纹(JA3/JA4)、HTTP/2 指纹是否与声称的浏览器一致
哪怕你的 JS 全跑通了、Cookie 也拿到了,一个脏 IP 依然会让你反复被挑战。
对抗难点在哪
难在它是多层联动的:
- JS 层:要能跑通挑战,拿到有效 Cookie
- 传输层:TLS 指纹要对得上(这是很多人栽的地方——用
requests直连,TLS 指纹一眼假) - 网络层:IP 信誉要干净
- 时间层:Cookie 有有效期,且与 IP/UA 绑定,换环境就失效
单点突破没用,要四个维度同时对齐。
识别特征
- 返回 403 / 503,页面标题是「Just a moment...」或「Attention Required」
- 响应里有
cf-ray、server: cloudflare头 - 需要
cf_clearanceCookie
横向对比
| 流派 | 判断对象 | 核心技术 | 静态分析难度 | 环境要求 | 综合强度 | 典型产品 |
|---|---|---|---|---|---|---|
| 动态执行流 | 代码本身 | 动态混淆 / eval / VMP 字节码 | 极高 | 中(需完整 JS 执行环境) | 高 | 瑞数 BotGate、顶象 |
| 设备指纹风控 | 设备环境 | 多维特征采集 + 模型打分 | 低(算法易扒) | 极高(环境一致性) | 高 | 同盾、数美、顶象 |
| 行为验证码 | 操作动作 | 轨迹采集 + 行为模型 | 中 | 高(需真实事件链) | 中高 | 极验、易盾、天御 |
| 边缘挑战 | 整体信誉 | JS Challenge + 指纹 + IP 信誉 | 中 | 极高(四层联动) | 最高 | Cloudflare、Akamai |
一句话总结各自防的是什么
- 动态执行流:防「静态读代码」——强度最低,但门槛最直观
- 设备指纹:防「假环境」——算法简单,环境最难
- 行为验证码:防「假操作」——轨迹真实性是核心
- 边缘挑战:防「不像人的整体流量」——维度最多,联动最紧
现实:大厂从来不是只用一种
单一流派都有明显短板,所以真实部署基本是混着上:
典型组合 A:瑞数 + 风控 SDK
瑞数负责让参数无法静态复现,风控 SDK 负责判断环境真伪。你就算把瑞数的参数跑出来了,环境分不够照样被降权。
典型组合 B:Cloudflare + 极验
Cloudflare 在边缘先筛一遍(挡掉大部分低成本流量和脏 IP),剩下的进源站再过极验(挡掉环境勉强过关但行为可疑的)。两层筛子,成本递增。
典型组合 C:指纹 + 无感验证 + 动态签名
首访静默采集指纹,可疑则触发无感验证,全流程参数由动态签名保护。用户几乎无感,但自动化成本极高。
这类组合的共同逻辑是:用低成本手段过滤掉 90% 的流量,把高成本手段留给剩下的 10%。
如果你是防守方:怎么选
- 只是想挡掉无脑爬虫和采集脚本 → 边缘 WAF + 基础频率限制,成本最低,收益最快
- 核心数据资产,且已被针对性研究 → 动态执行流(提高单次复现成本)+ 设备指纹(提高环境伪造成本)
- 涉及账号、交易、注册等敏感动作 → 行为验证码 + 设备指纹,重点在「动作真实性」而非「访问频率」
- 面向公网、流量大、来源杂 → 边缘挑战优先,先把脏流量挡在源站之外
一个常被忽略的点:分级防护比堆强度更有效。 全站上最重的方案,用户体验和运维成本都会失控;按接口价值分层,才是可持续的做法。
结语
把四个流派摆在一起看,会发现一个规律:
防护强度不取决于算法多复杂,而取决于它要求对手同时满足多少个独立条件。
动态执行流要求「代码可复现」,一个条件,所以能挡静态分析,但挡不住执行。
设备指纹要求「环境处处一致」,几十个条件,所以算法好扒、环境难补。
行为验证码要求「动作符合人类分布」,一个连续性条件,所以能挡脚本、难挡真人代理。
边缘挑战要求「代码 + 传输 + 网络 + 时间四层对齐」,四类条件叠加,所以综合最强。
理解了这条规律,再看任何新的防护产品,判断它属于哪一派、要求你满足哪些条件,会比记具体算法有用得多。

浙公网安备 33010602011771号