ARTICLE DETAIL

资讯详情

深耕网站视觉设计与运营推广的一线实战洞察。

网易易盾滑块验证自动化:图像识别与轨迹模拟实战

网易易盾滑块验证自动化:图像识别与轨迹模拟实战 简介网易易盾滑块验证DEMO是一份面向Web/App开发者的源码示例用于解决登录、注册等关键操作中自动化工具恶意攻击的问题也可作为验证码机制的学习样本。压缩包共3个文件含两个Python源文件及一个联系方式说明整体仅2KB小巧精炼一个文件负责滑块渲染、用户输入处理及服务器通信等核心逻辑另一个用作配置管理便于修改服务器地址、重试次数等参数。当前已有2252人学习下载。通过分析与运行该DEMO读者可深入理解滑块组件坐标计算、随机扰动图像生成、后端校验及安全策略等实现要点并可将整套流程集成到自身项目中依据实际安全需求调整验证规则是快速上手滑块验证开发的轻量实用资料。1. 网易易盾滑块验证-DEMO想做自动化登录先过这一关很多第三方站点并不直接用网易账号体系却把登录页的注册、找回密码、活动领奖接口接上了网易易盾滑块验证。人工拖动两秒通过脚本一上来就被层层的“验证失败”弹窗拦死。网上搜“带滑块验证的登录页面如何模拟登录”绕不开的就是这个DEMO级问题它不是一个库能解决的而是一整套图像识别加行为仿真流程。滑块验证的通过率直接决定了爬虫的登录成功率、UI自动化用例的有效性、甚至是批量账号操作的存活时长。这个DEMO的核心矛盾在于服务端校验的不仅是最终坐标对不对还会分析你从按下鼠标到松开之间产生的整条轨迹以及伴随轨迹提交的加密参数。因此一个能稳定通过的滑块DEMO至少要覆盖三件事用图像识别定位缺口、用速度模型伪造人类拖拽轨迹、用正确的参数格式提交验证请求。本文从这三个点出发把网易易盾滑块验证的前后端机制、本地实现代码、参数调优和工程化改造完整过一遍。适合正在做登录接口自动化、爬虫会话保持或UI回归测试的工程师。2. 滑块验证的核心机制缺口识别与加密参数从哪来2.1 前端JS把信息变成参数网易易盾滑块验证在页面上呈现的是一张缺口背景图和一个可拖动的滑块。用户拖动过程中页面内置的JS脚本会收集三类数据并编码进请求参数里。第一类是设备信息。初始化验证时易盾会从浏览器读取canvas指纹、WebGL渲染信息、时区、语言等特征生成一个设备指纹字符串后续请求中的fp参数就基于它。如果HEADLESS浏览器缺少WebGL和canvas指纹这个指纹的特征熵就会下降服务端会在参数校验阶段直接判定为可疑。第二类是图片信息。易盾的滑块验证组件会在每次验证时向服务端请求两张图一张带缺口的完整背景图和一张滑块本体图。图片通过base64格式下发这也是我们能拿到原始图像做本地缺口识别的入口。第三类是轨迹信息。从mousedown到mouseup之间JS会以一定频率记录鼠标坐标和时间戳。这个轨迹不能直接上报而是经过本地编码和加密后写入请求参数d中。注意d参数的加密方式随易盾SDK版本的不同会变化且压缩混淆后的JS代码会动态生成密钥这也是纯Python方案绕不开前端执行环境的原因。2.2 验证接口的时序与参数映射抛开页面交互网易易盾滑块验证的底层是一组HTTP接口在配合工作。以最常见的web端验证为例接口时序可以梳理成下表阶段接口路径核心参数返回关键值初始化会话/api/v3/getid, fp, typeacToken, 图片数据图片加载初始化返回-background, front发起校验/api/v3/checkacToken, d, cbvalidate, error结果确认校验返回validate验证通过与否我一般会先用浏览器开发者工具的“网络”面板手动拖动一次滑块把这个时序完整标注出来。需要注意初始化接口有时会直接返回base64图片有时只返回图片URL取决于页面接入的是完整版还是精简版组件抓包时不要照搬别人的参数表要确认自己目标站点的实际返回结构。同一页面元素上易盾还会注入动态的token和cb回调参数cb是JSONP格式的随机回调名。提交验证时服务端拿到d轨迹密文后会先解出轨迹点序列做缺口位置匹配和轨迹合理性判定整个过程大概在200到500毫秒内完成。2.3 滑块验证DEMO要复现的关键逻辑把这套机制落到本地复现DEMO需要实现三条逻辑线。第一条是像素级缺口定位。易盾缺口图与背景图之间的色差不大直接匹配灰度图容易失准。常见做法是把两张图都经过Canny边缘检测再对边缘图做模板匹配用边缘轮廓的相似度来定位缺口左上角坐标。匹配结果会有一个置信度参数低于0.5时通常需要重新截取图片。第二条是拖拽轨迹仿真。这是整个DEMO中区分度高的一步。真实的人手拖动轨迹不是匀速直线而是先慢启动、中间短暂加速、接近目标时减速微调甚至会有不超过5像素的回弹。如果生成的轨迹被服务端判定为“过于线性”无论缺口定位多准都会直接失败。第三条是参数提交与结果解析。提交check接口后返回的validate值是后续业务请求的凭证。要注意validate的有效期通常只有几十秒拿到后应立即拼接到下一步登录或业务请求中否则即使验证通过后续接口仍会报错。提示以上三条逻辑中前两条完全可以在本地用Python和OpenCV完成第三条由于加密参数的存在最常见落地方式是让浏览器真实执行易盾的SDK JS程序只注入拖拽动作。下章介绍具体实现。3. 用Python在本地把滑块DEMO跑起来3.1 环境准备与图像处理环境方面推荐Python 3.10及以上版本核心依赖是opencv-python、numpy、playwright和requests。其中playwright用于控制真实浏览器加载目标页面它能把鼠标动作序列直接注入合成事件让易盾SDK的监听代码拿到轨迹数据并自动生成加密参数。pip install opencv-python numpy playwright requests playwright install chromium图像处理的第一步是把页面上的背景图和滑块图都截取成PNG文件。用playwright的locator直接定位易盾组件的两个节点再调用screenshot方法截图。from playwright.sync_api import sync_playwright with sync_playwright() as p: browser p.chromium.launch(headlessFalse) page browser.new_page(viewport{width: 1280, height: 720}) page.goto(https://your-target-site.com/login) # 点击滑块按钮触发易盾验证码加载 page.click(.yidun_slider) page.wait_for_selector(.yidun_bgimg, timeout5000) # 截取背景图和滑块图 page.locator(.yidun_bgimg).screenshot(pathbg.png) page.locator(.yidun_jigsaw).screenshot(pathfg.png) browser.close()上述代码中的.yidun_slider、.yidun_bgimg、.yidun_jigsaw是易盾前端组件的标准类名覆盖了绝大多数接入页面。如果你的目标站点对类名做了二次封装需要在开发者工具里确认实际渲染的DOM一般这组类名仍然存在只是外层多了自定义class。截图成功后先把fg.png和bg.png同时放到代码目录下方便下一步做缺口定位调试。3.2 缺口识别Canny边缘加模板匹配拿到两张截图后用OpenCV来定位缺口中心的x坐标。我一般会先转灰度再分别做Canny边缘检测最后用matchTemplate做模板匹配。直接匹配原始灰度图有两个问题一是滑块图本身带有阴影会干扰匹配结果二是缺口处图像是镂空的边缘信息才是真正的辨识特征。import cv2 def find_gap(bg_path, fg_path): bg cv2.imread(bg_path, cv2.IMREAD_GRAYSCALE) fg cv2.imread(fg_path, cv2.IMREAD_GRAYSCALE) # Canny边缘检测低阈值100高阈值200 bg_edge cv2.Canny(bg, 100, 200) fg_edge cv2.Canny(fg, 100, 200) # 模板匹配返回归一化相关系数矩阵 result cv2.matchTemplate(bg_edge, fg_edge, cv2.TM_CCOEFF_NORMED) _, max_val, _, max_loc cv2.minMaxLoc(result) x, y max_loc # 返回缺口左上角坐标和匹配置信度 return x, y, max_val这段代码里Canny函数的两个阈值控制边缘提取的敏感度。100和200这对参数是我在大多数易盾背景图上调试出来的通用值背景图上的干扰纹理比较多时把低阈值提到150能减少误检如果缺口边缘断裂明显则把高阈值降到150。matchTemplate的TM_CCOEFF_NORMED方式对光照差异有较好的鲁棒性返回值越接近1说明匹配越可靠。拿到max_loc后实际拖拽目标点需要再加上滑块图宽度的一半因为模板匹配返回的是左上角。3.3 轨迹模拟加速度模型替代匀速直线轨迹是滑块验证区分真人的核心特征。一个最原始的误区是把滑块的CSS像素距离等分成几十个点挨个move这种轨迹的加速度恒定、时间间隔均匀在服务端拟合曲线上会表现为一条标准直线基本必定失败。我用的轨迹生成策略是分段加速度模型import random import time def generate_track(distance): track [] current 0 v 0 t 0 mid distance * 0.7 while current distance: # 前70%距离匀加速后30%匀减速 if t 0.6: a random.uniform(2.0, 3.5) else: a random.uniform(-3.0, -1.5) v a step v * 0.1 if current step distance: step distance - current current step track.append(round(current, 2)) t 0.1 # 模拟接近终点后的回弹修正 track.append(distance - 1.5) track.append(distance) return track代码里的0.6是加速段与减速段的分界比例配合随机加速度范围可以模拟出先快后慢的拖动手感。回弹修正的两个点模拟的是人手滑过目标点后往回微调的动作。生成track后还需要转成鼠标实际移动事件每步间隔控制在8到15毫秒之间随机取值这一步能让时间戳分布更接近真实合成事件的产生节奏。3.4 Playwright注入轨迹与提交验证轨迹生成后用playwright的鼠标方法依次执行移动和按下/松开。关键在于每次移动后不要sleep固定时长而是随机睡眠并且不要用mouse.move直接跳转到终点要按track列表逐点走。import time # slider_box是滑块元素的bounding_box slider_box page.locator(.yidun_slider).bounding_box() start_x slider_box[x] slider_box[width] / 2 start_y slider_box[y] slider_box[height] / 2 # 按下滑块 page.mouse.move(start_x, start_y) page.mouse.down() # 按轨迹逐点拖动 for point in track: page.mouse.move(start_x point, start_y, steps1) time.sleep(random.uniform(0.008, 0.015)) # 松开鼠标 page.mouse.up() # 等待submit结果 page.wait_for_selector(.yidun_verify-status, timeout5000)这段代码执行时浏览器里的易盾SDK会认为发生了真实的mousedown、mousemove和mouseup事件序列它自己会把这组坐标和时间戳处理成加密的d参数。你不需要知道加密算法的细节这正是Playwright方案相比纯HTTP请求方案的优势。注意页面顶部如果启用了WebDriver检测还需要在启动浏览器时加上禁用自动化控制标志的参数。4. 把DEMO调到能过4个必调参数和3个常见坑4.1 四个必调参数从本地跑通到稳定通过中间隔着的不是某一行代码而是几个参数和阈值的配合。以下四个参数是我做网易易盾滑块DEMO时调整频率最高的参数推荐范围失败特征Canny低阈值80-150缺口边缘断裂匹配置信度低于0.5目标点偏移修正x 滑块宽度/2 ± 2验证后提示“拖动滑块到正确位置”轨迹总时长500-1200ms短于400ms容易触发速度检测回弹点幅度1-3px回弹超过5px被判定为异常抖动目标点偏移修正是最容易出错的。模板匹配返回的是缺口左上角坐标但服务端比对的是滑块本体中心的位置。滑块图本身就比缺口大一圈必须把缺口x坐标修正为“缺口左上角x 滑块图宽度/2”。不同接入方在CSS中对滑块图片缩放的比率不同如果总是偏差固定像素需要检查页面background-size属性按实际显示比例换算偏移量。轨迹总时长和回弹点幅度直接关联到行为判定的得分。真实人手拖动一个缺口距离的滑块通常不会低于400毫秒太快说明你直接用了坐标跳转。回弹不是必须的但1到3像素的轻微回弹反而会提高轨迹的“人味”。4.2 三个常见坑坑一headless模式透出自动化特征。无头浏览器在canvas指纹和WebGL渲染结果上与真实Chrome有明显差异易盾的fp指纹会直接命中黑名单。解决方式是用headlessFalse先跑通逻辑真正上线时用playwright的headless新版本或添加stealth插件补环境特征。坑二截取的背景图和滑块图尺寸不一致。如果滑块图是通过CSS拉伸显示的直接对原始PNG做模板匹配就会失准。我一般会在screenshot之前先获取两个元素的bounding_box确认它们的宽高比是否一致不一致时用cv2.resize把滑块图缩放到背景图的实际显示尺寸。坑三验证通过后validate被当作永久凭证。validate有效期很短通常只够拼接到一次登录请求中。如果你在check接口返回后还先打印日志、再查询数据库、再发后续请求大概率会碰到validate失效的报错。正确做法是把validate、acToken和业务参数一次性组装提交。# 错误示范打印日志拖慢了提交节奏 result check_captcha(acToken, d) print(f验证结果: {result}) # 正确方式拿到validate立即拼接到登录请求 validate check_captcha(acToken, d) login_resp requests.post(https://target-site.com/api/login, json{username: username, password: pwd, validate: validate}, timeout3)这段代码里check_captcha返回的validate如果不立即使用就丢了时效性。实际场景中更稳妥的做法是把验证和登录流程放到同一个会话上下文里不要中途切换requests.Session或重建连接。5. 从DEMO到通用滑块方案队列、降级与模型升级当目标从“跑通一次验证”变成“批量账号登录”时滑块DEMO的架构需要改三个地方。第一是验证任务的队列化。一个账号的初始化、截图、识别、拖动、提交是五步串行操作其中截图和拖动需要占用浏览器实例纯计算部分则不需要。我一般会把Playwright浏览器实例做成一个独立队列worker同一时刻只跑一个用户的拖动动作避免多个任务在同一个浏览器上下文里互相穿插导致事件序列错乱。写入队列时每项任务包含独立的代理IP和用户指纹保证不同批次的验证会话之间没有关联性。第二是降级策略。Playwright方案稳定但并发成本很高。当账号量级上来后可以考虑把step3中的纯API方案作为降级链路用requests请求初始化接口获取图片本地识缺口通过Node子进程执行页面中提取出的SDK加密函数来生成d参数。这个方案的单个会话内存占用比Playwright低十倍以上但它依赖你维护一份与目标站点版本匹配的SDK JS代码易盾SDK升级后需要重新适配。常见做法是先用Playwright跑通全部流程再逐步用纯API方案替代并以真实通过率作为切换指标。第三是缺口识别模型的升级。模板匹配在背景简单时表现很好但如果目标页面用了复杂的噪点背景或压缩率极高的JPEG图Canny边缘会出现大量伪边缘这时可以换成轻量语义分割模型来输出缺口mask。有一个快速的中间方案是用cv2的形态学闭运算先把噪点边缘连通再提取外接矩形import cv2 bg_edge cv2.Canny(bg, 100, 200) # 闭运算消除小洞和断裂 kernel cv2.getStructuringElement(cv2.MORPH_RECT, (5, 5)) closed cv2.morphologyEx(bg_edge, cv2.MORPH_CLOSE, kernel) # 找外部轮廓取面积最大的作为缺口 contours, _ cv2.findContours(closed, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE) contours sorted(contours, keycv2.contourArea, reverseTrue) x, y, w, h cv2.boundingRect(contours[0])对比模板匹配方案轮廓提取不需要滑块图参与定位结果也更稳定。闭运算的核大小决定了边缘连通的范围——核太大会把缺口和干扰纹路连成一块一般从5起步调试。后续上线时还可以把模型换成YOLOv8-seg做实例分割但考虑到推理延迟和GPU资源纯CPU场景下形态学方案仍然是性价比之选。本文还有配套的精品资源点击获取
返回列表