滑块验证这事,看着简单,但坑就藏在细节里。先说一个核心判断:后端必须掌握全部主动权——缺口图、坐标、校验逻辑,全得放在服务端。前端要是自己挖图或者算缺口的像素坐标,那防刷就形同虚设了。 后端必须返回 backgroundImg、sliderImg、blockX、blockY 四个字段 前端自己“挖图
uni-app实现自定义风格滑块验证防暴力刷
时间:2026-06-27
浏览:587
文章目录
滑块验证这事,看着简单,但坑就藏在细节里。先说一个核心判断:后端必须掌握全部主动权——缺口图、坐标、校验逻辑,全得放在服务端。前端要是自己挖图或者算缺口的像素坐标,那防刷就形同虚设了。
后端必须返回 backgroundImg、sliderImg、blockX、blockY 四个字段
前端自己“挖图”或者“算缺口位置”是典型的错误做法。blockX 是缺口在背景图上的真实横坐标,单位是像素,后端在生成图的那一刻就固定了。前端要做的很单纯——把滑块拖到这个 X 附近。blockY 则决定了缺口图在背景图上的垂直对齐位置,少了它,拼图直接错位。所有图片必须是 base64 编码,或者是同源的 URL,这样才能避免在小程序或者 APP 端用 canvas 的 drawImage 时出现跨域问题。
backgroundImg和sliderImg必须来自同一次后端生成,尺寸必须一致,缩放比例也要一致——不能一张是 500x300,另一张是 510x290。- 如果用网络图,在安卓真机上需要先用
uni.downloadFile缓存到本地临时路径,然后再传给drawImage,否则很可能画不出来。 - 还有一点很关键:blockX 的值不能被前端推导出来。比如通过图片宽高加随机数生成的那种,攻击者完全可以绕过请求,直接伪造一个 blockX 提交。
touchmove 里限制 X 轴范围,实时更新滑块的 left
千万别用 @click 或 @longpress 来模拟拖拽——它们没法连续捕获位移,而且在真机上触控精度也不够。必须老老实实用 touchstart、touchmove、touchend 这三个事件手动计算。
- 在
touchstart的时候记录下起始的clientX和滑块当前的left值。然后在touchmove中,通过e.touches[0].clientX - startX + startLeft来实时算出当前的 left。 - 用
Math.max(0, Math.min(computedLeft, maxWidth))来严格限制范围。比如maxWidth设为 280,这样滑块拖不出界,也不会出现松手触发错误校验的情况。 - 滑块 DOM 元素只更新
left样式就行,千万别每帧都去重绘 canvas。H5 和小程序的性能差异会暴露逻辑漏洞——尤其是低配手机上,一帧帧重绘 canvas,卡顿感立刻就能让人看出来实现有问题。
touchend 里提交 normalizedOffset,不是像素值
直接提交像素 left 值是个危险的坑。不同屏幕宽度下,同一次操作产生的像素值不同,后端的容差就很难统一,而且容易被逆向分析出真实的 blockX。正确的做法是归一化处理:
const normalized = parseFloat((left / maxWidth).toFixed(3))
同时必须附上本次验证的唯一标识,比如 captchaId(由后端下发并绑定 session 或手机号)。后端收到请求后,按同样的比例反推像素位置:userX = Math.round(normalized * maxWidth),然后再和原始的 blockX 做 ±5 px 的容差比对。额外加上时间戳和简单的设备指纹(比如 UA 片段加屏幕宽高),能辅助风控判断,但核心逻辑还是服务端绑定加归一化校验。
防暴力刷的关键不在前端动画或提示语
说句实话,所谓“防刷”,本质就是让同一张图不能被重复提交,也不能被 A 拿去给 B 用。在前端加个“3次失败锁1分钟”的 UI 提示,说句不好听的,攻击者根本不会走 UI——他们直接跳过界面,调接口就行。
- 每次调用验证接口,后端必须生成新的
captchaId,并且销毁旧 id 对应的所有图数据。这是最基本的。 - 用户提交时,后端第一件事是查
captchaId是否存在且未使用过。第二件事才是比对normalizedOffset。顺序不能错——先校验身份,再校验位置。 - 前端的 reset 方法(比如叫
refreshScale())只能重置 UI 状态,不能绕过后端重新发图的逻辑。否则一切都是白搭。 - 如果业务允许,建议滑块验证和信息验证码二选一,而不是叠加。叠加反而容易被自动化工具枚举,反而增加了攻击面。
其实还有一个最容易被忽略的点:blockY 不仅影响视觉对齐,在 iOS 小程序上,如果 Y 偏移没对准,canvas 的 clip 区域会错位,导致缺口图显示在错误的高度,用户永远拼不对。但这不是前端的 bug,而是后端漏传或者传错了值——这种事情实测碰到过好几次了。
实用工具推荐
绿化、压缩、噪点和虚拟水印,自由调节做旧程度。
选择画质和输出格式,预览压缩前后的大小。