← 返回文章列表

滑块卡住了,还是风控拦住了?从图像坐标到服务端验签

滑块验证码的故障可能出在图片渲染、拖拽交互或服务端核验。通过自制图片、可复现的交互用例和官方测试环境,可以分别定位坐标偏移、事件丢失、令牌过期与配置错误,同时减少对真实用户的误拦。

滑块卡住了,还是风控拦住了?从图像坐标到服务端验签

一、滑块拖到底,为什么还是没过?

登录页弹出一张图,用户把拼图块拖到缺口上,页面却提示验证失败。客服看到的是一张截图,前端同事看到的是滑块确实停在了目标附近,服务端日志里可能只留下一句校验失败。三方说的都没错,只是各自看到了不同环节。要找到原因,先弄清楚失败发生在图片显示、拖拽交互、凭证返回,还是后端核验。

以常见的第三方接入方式为例,业务页面先加载验证码组件,组件发起挑战并收集交互结果。挑战通过后,组件把短时有效的凭证交给业务前端,前端再随登录或注册请求把它传给业务后端。后端通过供应商接口核验凭证,然后决定是否继续处理业务请求。页面显示通过,只说明组件完成了自己的那一步;业务接口是否接受这次请求,还要看服务端核验结果。

排查时,最好从用户按下滑块开始还原时间线。图片没加载出来,先看静态资源和组件初始化;滑块能动却在松手时跳回起点,先查事件和页面状态;组件已经返回凭证,登录仍报失败,就沿着业务请求查凭证是否传到后端、是否过期,以及核验接口有没有响应。把这些情况都写成同一个错误码,用户只能不停重试,工程师也很难从日志里知道该找谁。

复现记录里可以放上页面版本、浏览器、设备类型、失败阶段和请求编号,让前后端能找到同一次尝试。验证码原始凭证、服务端密钥和完整指针序列不必写入常规日志。如果问题只在手机上出现,优先补齐屏幕方向、页面缩放和输入方式;一段带操作步骤的录屏,往往比一句“滑块偶尔失灵”更能缩小排查范围。

二、用自制拼图查清坐标误差

要搞懂图像定位,拿自己生成的拼图做实验最直观。准备一张背景图,把同一个轮廓画在几个已知位置,再生成不同尺寸、压缩质量和亮度的版本。因为每张图的真实坐标事先就有记录,检测结果可以直接和标注比较。普通文字识别关注图里写了什么;这个实验关注轮廓画在哪里,主要看边缘、形状和坐标误差。

在 OpenCV 里,灰度化可以先把颜色差异简化为亮度差异,高斯滤波能压低细碎噪声,Canny 边缘检测则把明显的亮度变化提取出来。做对照实验时,每次只改一个条件:固定背景改变压缩质量,或者固定压缩设置改变显示尺寸。把边缘图和原图并排看,就能分辨轮廓是被滤波抹掉了,还是被背景纹理干扰了。阈值调得越敏感,看到的细节越多,冒出来的杂边也可能越多。

模板匹配适合比较外观和尺寸接近的图块;轮廓比较关注的是形状本身。比如用 Hu 矩比较两条轮廓,可以得到一个形状差异分数,但这个分数不告诉你轮廓在整张背景图上的位置。对单独的拼图块计算质心,结果也只属于那张小图。检测框如果从裁剪区域里得到,记录结果时还要加上裁剪原点的偏移,才能回到原图坐标。每次画框都偏向同一边,先查坐标来源,再考虑算法有没有问题。

从原图走到网页,还要做一次换算。六百像素宽的原图完整显示在三百个网页像素宽的区域内时,原图距左侧二百像素的点,对应显示区域内距左侧一百个网页像素。若容器还留了边,或者图片为了填满容器被裁掉一截,就得按实际可见区域算起点。测试报告最好分开记原图定位误差和页面绘制误差:前者能定位图像处理问题,后者更容易暴露布局和坐标转换的毛病。

三、把拖拽问题留在自己的组件里复现

在自研拼图组件里,拖动可以拆成按下、移动、释放和取消四种状态。按下时记住手指或鼠标在滑块上的落点,移动时根据指针位移更新滑块,释放后结算状态。这样用户从滑块右缘按下时,滑块不会突然把中心挪到指针下面。用同一个测试用例分别从中间和两端开始拖,最容易发现这类起步跳变。

很多拖拽故障只有在手指离开滑块后才出现。桌面上,鼠标可能移到轨道外再松开;手机上,浏览器可能把一次拖动识别成页面滚动,随后发出取消事件。自研组件可以用指针捕获跟踪拖动,并在收到取消或失去捕获时清理状态。测试时让指针移出控件、让页面失去焦点,再回来开始下一次拖动,检查滑块能不能恢复。若下一次按下仍沿用上一次的落点,问题通常出在状态没有清干净。

贝塞尔曲线适合用在本地演示里,比如让拼图块在释放后平滑回到起点。控制点决定曲线的形状,动画如何随时间推进则取决于时间映射。把曲线参数等间隔取样,不会自动得到先加速再减速的效果;当几个控制点处在同一条水平线上,路径也不会凭空出现上下摆动。测试回弹时,可以固定动画时长,检查开始位置、结束位置,以及动画中途再次按下时组件会如何响应。

界面自动化也可以保持简单。在自有页面上用浏览器测试工具执行固定的按下、移动和释放,断言滑块不会越过轨道,取消后可以重拖,窗口变化后位置会重新计算。鼠标、触屏和键盘分别覆盖各自支持的操作。对第三方组件,端到端测试应走供应商提供的测试机制;日常回归主要验证业务页面收到成功、失败或过期结果后,会显示什么、提交什么。

四、接入易盾或极验时,把测试和生产分开

已经使用易盾、极验等验证码服务的团队,可以先查对应产品与版本的官方接入文档,确认是否提供测试应用、沙箱或专用测试配置。条件允许时,在测试环境跑一遍真实集成;没有对应能力时,可以在自有系统的测试环境里用替身服务返回预设结果,覆盖登录或注册流程。替身只用于检验业务如何处理结果,生产环境仍按正式流程核验,测试配置和生产密钥也要分别管理。

接入代码可以把供应商调用收口到一个小模块。业务只需要知道验证是否通过、失败能否重试,以及排查时要带上哪个请求编号;供应商返回字段的差异,由模块内部处理。服务端密钥留在后端,核验请求设置合理的超时。如果产品要求核对挑战所属的场景或会话,就按文档实现,并实际测试把注册场景的结果提交到登录接口时会发生什么。

重复提交是个容易漏掉的细节。用户点了一次登录,按钮没反应,又点了一次;第二个请求到达时,第一个可能已经用掉凭证。前端可以在请求进行中禁用提交按钮,并及时显示处理状态。对注册等会产生写入的接口,还要考虑幂等:同一次操作被重复送达时,应当返回已有结果或明确告知状态,不能创建两条记录。遇到凭证已过期时,应让用户重新发起挑战,避免页面反复提交旧值。

上线前还要演练网络超时、组件资源加载失败和供应商配置错误。三种情况都可能让按钮旁出现红字,但处理方式不同:超时可以提示稍后再试,资源加载失败可以提供重新加载入口,配置错误则应该触发内部告警。用户提示只需说清眼下能做什么;值班人员需要看到失败环节、耗时、产品版本和错误分类,才能判断是业务发布引入的问题,还是依赖服务出现异常。

五、用漏斗和复测判断有没有误伤用户

验证码上线后,单看通过率很容易得出错结论。把流程拆成触发、加载完成、开始交互、挑战通过、后端核验和业务完成几个阶段,再分别看每一步流失了多少人。加载环节下滑,优先排查资源请求和初始化;挑战通过比例没变,后端核验却突然失败,检查服务端配置和调用链;核验成功但注册量下降,则要继续看表单和提交接口。

比较数据时要说明分母。把每次重试都算成一次挑战,和按一次登录流程统计,会得到不同的比例。前者适合看组件负担,后者更能回答有多少用户最后办成了事。按浏览器、设备、页面版本和网络条件做对比也很有用。整体数字没有波动,并不代表某款手机上没有故障;反过来,小样本里的几次失败也不足以判断整个平台出了问题。

验收时给不方便拖动的人留一条明确的路。如果供应商提供可访问的替代挑战,就检查它能否通过键盘进入、是否有清晰的焦点提示、读屏软件能否读出错误和重试入口。使用放大显示或触控辅助设备时,也要确认验证码弹窗不会把关闭按钮挤出屏幕。对于一直无法完成挑战的真实用户,支持人员应能根据请求编号判断失败阶段,再引导用户走经过业务核验的替代流程。

比如一次发布后,移动端的拖动失败增加,桌面端却没有变化。可以先拿一台受影响设备复现,记录按下、取消和重新按下的顺序,再对照最近一次样式改动。若确认横向拖动被页面滚动打断,就修正自有控件的交互范围,并保留页面其他区域的正常滚动。修完后用同一设备复测,再看移动端从开始交互到挑战通过的流失是否回落。这样,下次遇到类似投诉,团队手里就有可重复的步骤和能对照的数据。