
身在一线做测试开发这两年打交道最多的就是各种验证码登录场景易盾的滑块、点选、无感知几乎成了标配。我最初也以为“滑块就是拖一下、点选就是点一下”直到把整套带验证码的登录页放进自动化脚本里跑才发现背后的逻辑远不止表面那一次交互。这篇就把我这大半年折腾易盾验证码的经验做个梳理从验证码机制、前端信号分析到自动化场景下真正能落地的应对思路一次讲透。先说明一下方向本文聚焦的是合规场景下的自动化测试和调试分析不讨论任何绕过风控从事黑灰产的做法。你如果是测试开发、RPA工程师或者正在维护自己的爬虫采集项目并且卡在了登录验证这一步这篇文章应该能帮你少走不少弯路。京东滑块、淘宝滑块、阿里滑块这些同类型产品底层思路大多相近把易盾研究明白其他家你也会看得更清楚。1. 易盾这三类验证码到底在验证什么1.1 滑块验证码不只看轨迹“像不像人”先说滑块。很多人以为滑块验证就是判断用户是不是把拼图拖到了正确位置位置对就能过。真实情况是滑块验证码从你按下鼠标那一刻起就在采集一组连续的行为数据按下位置、移动轨迹、停顿时间、加速度变化、松手坐标这些信息会被打包成一个加密参数提交给服务端由风控系统打分。我以前用 Selenium 直接模拟拖动滑块轨迹是均匀的直线结果每次都提示“未通过安全验证”。后来抓包对比自己手动拖和脚本拖的差异才明白人手的拖动轨迹是带有微小的上下抖动和不均匀加速的而代码生成的线性轨迹太“完美”了反而像机器。另外滑块验证还有一个常见的“兜底网格”机制。也就是说即使你的落点坐标在允许误差范围内如果行为轨迹的可疑度高服务端依然会要求二次确认。这里有个很容易忽略的细节拖动速度突变点。人工拖动时在起手和落手两个位置往往会有明显的速度变化而纯模拟的匀速运动没有这个特征。所以如果你在用 Playwright 或 Selenium 做滑块调试至少要保证轨迹是非线性的并且加入随机停顿。1.2 点选验证码语义理解和坐标精度一起考点选验证码看起来更简单识别图片里的目标物体然后点对应的文字或图案。但易盾的点选不是单纯考“你认不认识汉字”或者“你眼神好不好”它会在图片里埋很多干扰项。比如让你依次点击“汽车”“行人”“交通灯”但画面里可能有大面积相似色块、局部遮挡、甚至语义模糊的目标机器识别容易误判人脸却能轻松区分。更关键的一点是点选顺序。易盾点选一般要求按指定顺序点击比如“先点汽车再点交通灯”这个顺序信息会被记录进行为数据。如果你脚本随意改点击顺序即使坐标识别正确同样会触发风控。点选验证码还有一层“邻近度判定”。不是说点中了目标中心就行而是点击坐标与目标物体实际区域的相对位置必须合理。我之前遇到过一个情况脚本识别到目标后机械地点击目标左上角固定偏移位置结果成功率很低。后来分析正常用户操作发现不同用户点击目标时落点分布是靠近中心的且带有一定随机性固定偏移反而暴露了机器特征。1.3 无感知验证码在交互开始前它已经给你打过分了无感知验证码设计的出发点是尽量避免打断用户操作真正的验证发生在后台。用户可能什么都没做验证就通过了。但“无感知”不代表“无校验”它实际上集成了设备指纹、浏览器环境特征、用户行为序列和网络特征的综合评分体系。比如你打开一个带易盾无感知验证的页面它会静默采集你的 User-Agent、Canvas 指纹、WebGL 信息、屏幕分辨率、时区、语言甚至浏览器安装了哪些插件。同时在页面加载过程中记录鼠标移动、滚动行为、点击间隔。这套数据整合成一个风险分分数达标直接放行不达标才会降级弹出滑块或点选。做自动化测试时最痛苦的就是这个脚本刚打开页面还没碰到登录按钮整体风险分就已经很低了。因为无头浏览器Headless Browser的 Canvas 指纹、显卡渲染特性跟正常浏览器差异非常明显易盾几乎是一眼就能识别。这也是很多人在本地普通浏览器里手点没问题换成脚本环境就触发验证的根源。2. 逆向分析的正确打开方式先搞清楚前端在跟后端说什么2.1 浏览器开发者工具先从网络请求里找线索不管你是要做自动化测试还是写采集脚本遇到验证码第一件事绝对不是去写模拟代码而是打开浏览器开发者工具看网络请求。易盾的验证流程一般会涉及几个关键接口初始化时获取验证码配置、用户操作完成后提交验证结果、最后返回一个 token 给业务系统。按下 F12 进入 Network 面板勾选 Preserve log然后在页面上手动操作一次完整验证你会看到一串请求。重点关心那些名字里带 check、validate、verify、captcha 这类关键词的请求点开看参数和返回值。易盾的返回包里一般会带上一个验证 token业务后端拿这个 token 去请求易盾服务端换确认结果。我之前踩过一个坑只看 POST 请求的载荷忽略了请求头里几个自定义字段。结果我把参数都模拟齐了还是被拒最后才发现易盾校验了请求头里的一个自定义签名头那个值是由 JS 在提交前动态生成的。所以不要只盯着 bodyheaders 里加了什么、cookie 有没有变化通通要记录。2.2 JS 断点调试找到加密参数生成的入口如果是纯前端代码你可以通过搜索关键字来定位加密逻辑。在 Sources 面板里按 CtrlShiftF 全局搜“check”“captcha”“acToken”这类字段名一般能找到对应的 JS 文件。把断点打在可疑位置重新触发验证就能在 Call Stack 里看到整个调用链。易盾的加密流程里有一个明显特征它会把设备和行为数据放到一个数组里然后通过自定义的序列化函数转成字符串再经过 AES 或 RSA 加密最后 base64 编码放进请求参数。你在断点处看到的往往不是明文的 plaintext而是一个 json 对象被逐步处理的过程。如果你是写自动化脚本并不一定需要完整还原加密算法——只要能在运行时把那段 JS 在浏览器环境里正常执行拿到它生成的加密串后续提交就能续上。2.3 行为采集信号容易被忽略的“隐形参数”很多人在逆向分析时关注加密参数却忽略了另一个层面的东西行为信号。易盾会在页面里监听 mousemove、mousedown、mouseup、touchstart 等事件把这些事件的时间戳序列、坐标序列按特定规则编码进验证数据。这意味着即使用脚本提交的加密参数格式完全正确如果里面携带的“行为序列”过于规律比如所有轨迹点等间距分布、时间戳完全相同风控照样能识别出异常。处理办法通常是在生成行为序列时加入一定范围的随机扰动坐标加一点偏差、时间间隔加一些随机抖动同时保证整体序列符合正常人操作的速度分布特征。逆向分析做到这一步本质上已经不是在破解算法了而是在模拟“人”的行为特征。这也是测试脚本和真人用户之间最难抹平的一道鸿沟。3. 实操自动化测试中处理易盾验证码的几种合规思路3.1 团队内部环境策略直接让开发关掉验证码如果你做的是自己公司业务的自动化测试最优解往往不是跟验证码硬刚而是跟开发、运维协调在测试环境或灰度环境关闭验证码服务。很多团队在接入验证码时都预留了开关配置比如根据域名或用户 IP 判断是否需要启用风控校验。这个策略既省事又稳定避免自动化脚本把大量时间耗在验证环节。具体操作上可以在配置中心加一个白名单开关测试环境的域名直接 return 一个固定 token绕过易盾二次校验。这样 UI 自动化脚本可以直接稳定登录跑用例的时候不会再闪出奇怪的人机验证弹窗。唯一要注意的是关闭验证码的环境要和线上配置隔离清楚防止配置误用。3.2 人工接管测试脚本卡住了临时让人点一下有些场景下没法关验证码比如你测试的目标系统是第三方提供的或者你采集的是公开网站上需要登录才能看的数据。这时候最朴素的办法就是人工接管脚本执行到验证码步骤时暂停弹窗提醒测试人员手动完成滑块或点选验证通过后脚本继续执行。在 Selenium 里可以用 input() 阻塞等待或者在 Playwright 中通过 page.pause() 进入调试模式操作完成后手动恢复脚本。这种做法的优点是稳妥不碰任何风控红线。缺点是自动化程度低尤其频繁跑回归时会很费人力。所以我通常只在调试阶段用人工接管正式回归时还是优先走接口层方案。3.3 接口层处理直接越过 UI走内部业务接口比人工接管更高效的方式是接口层处理。我们做自动化测试时通常登录态是通过一个 session 或 token 维持的那为什么非得每次都在 UI 上完整走一遍登录流程可以直接调用业务系统的登录接口或者通过测试数据工厂提前准备好已登录的会话。比如用 Playwright 先把登录后的 storage_state 存成 JSON 文件后续测试用例直接加载这个状态跳过登录 UI 步骤。这样连验证码都不需要碰。唯一的坑是 storage_state 有有效期过期后需要重新登录。可以写一个定时任务让脚本在凌晨自动更新一次 storage_state保证白天跑用例时登录态是新鲜的。3.4 灰度白名单机制让你的脚本在风控眼里“像个人”如果既不能关验证码、也不想每次人工点还有一种折中方案申请让风控系统按 IP 或设备指纹做白名单。有些业务方为了兼容内部自动化工具会开放一个白名单通道例如把公司办公网出口 IP 加进白名单这些 IP 发起的验证请求默认给高信任分。这个方案比较偏业务合作适合自己公司的系统或者有运维联系的业务方。你在调研需求时可以直接问对方风控团队“你们有没有测试专用白名单通道”很多时候答案是有的只是没人提就没对外开放。申请到白名单后测试脚本基本不再需要处理各种弹窗验证稳定性提升明显。4. 常见问题与排查技巧实录4.1 滑块总是提示“网络异常”或“行为异常”这是最经典的一个坑。明明滑块拖到位置了页面还是报错。我排查过的案例里原因基本集中在三处第一轨迹过于线性第二请求参数缺失或用错了环境第三IP 被风控标记了。先换一个干净的网络环境试一次如果换网络就好了说明问题出在 IP 信誉上如果换网络依然不行就回到轨迹参数上排查。其实这里有一个小技巧浏览器里打开一个带易盾验证的页面手动拖一次滑块同时用抓包工具记录下整个交互过程。把你手动操作的轨迹采样出来再去调整脚本里的轨迹函数。这个做法模拟出来的轨迹和真人最接近比凭空设计曲线靠谱得多。4.2 点选验证码定位不准点选验证码的图片定位通常靠模板匹配或 OCR 识别不管用哪种方式都可能出现偏差。我遇到过最典型的是本地截图识别坐标没问题但脚本执行点击时总是偏了几像素。排查后发现是浏览器窗口缩放比例不一致导致截图坐标和真实点击坐标不一致。处理方式是在脚本开头统一设置窗口大小和缩放比例取消浏览器的自动缩放。另外点击目标时不要机械地定位到目标左上角或中心点固定坐标而是以识别框中心为基准加上一个随机偏移量比如 ±5 像素内这样更接近人类行为。多次失败后还要检查验证码是否已经刷新图片变了但你还在用旧坐标自然永远点不对。4.3 无感知验证导致整个自动化脚本全部失败无感知验证码最隐蔽因为页面没有任何弹窗提示用户甚至不知道验证发生了。但脚本跑起来就是登录不上接口层面偶尔还会回一个奇怪的状态码。排查时看 Network 面板里有没有额外多出来的验证请求尤其是页面初始化阶段发的那几个。我在实际项目里遇到过页面加载时易盾无感知验证已经静默执行完但因为脚本用的是 Testing 环境标志明显的浏览器参数被判定为高风控服务端悄悄把登录接口的返回从成功改成了假成功——返回了 200但不带真实 session。这种问题很难发现排查思路是直接用同一套代码在普通浏览器里跑一遍对比是否存在差异。如果普通浏览器正常、脚本环境异常优先检查浏览器指纹相关配置。4.4 调试时找不到加密参数无从下手全局搜索搜不到、断点打不中也时有发生。易盾的 JS 文件有时是混淆压缩过的变量名全是一两个字母搜索关键字可能命中不了。这时候换个思路不要从文件内容入手而是从调用栈入手。先在 Network 面板找到发送验证结果的请求看 Initiator 列点击展开会显示这个请求是由哪个 JS 文件的哪一行发起的。顺着调用栈往上翻就能定位到生成请求参数的那个函数再看它引用了哪些变量、调用了哪些函数。这个方法比盲目搜索关键字高效得多前提是你的浏览器开发者工具要够熟特别是 Initiate 和 Call Stack 两个面板的使用。另外有时候混淆代码里会用数组展开的方式来隐藏字符串先把控制台里的全局变量 dump 出来看看比自己读压缩代码轻松很多。4.5 关于“模拟登录”热词背后的一点提醒最近“带滑块验证的登录页面如何模拟登录”这类问题很火京东、淘宝、阿里的滑块加密也被反复拿出来讨论。我建议你在网上搜索相关方案时留个心眼很多所谓的成品源码要么是钓鱼的要么本身就带后门。尤