滑块验证必须双路径监听touch/mouse事件并防默认行为,位移判定需结合起点、终点、方向、容差与时间戳,解锁后须服务端校验且前端状态限时失效。

不能用 input[type="range"] 直接套,它不验证拖拽行为、可被点击跳转、键盘操控形同虚设,安全水位极低。
为什么 touchstart + touchmove 是必须的
移动端 mousedown 在 iOS Safari 和部分安卓 WebView 中常被拦截或延迟,仅监听鼠标事件会导致手势失效。真实场景必须双路径捕获:同时绑定 touchstart/touchmove 和 mousedown/mousemove。
-
touchstart中立即调用e.preventDefault(),防止页面滚动抢走事件 - 记录
e.touches[0].clientX(触屏)或e.clientX(鼠标)为startX - 容器元素必须设置
touch-action: none,否则 iOS 会默认触发缩放或滚动 - 滑块宽度建议写死(如
80px),避免因 zoom 或字体缩放导致位移计算偏移
判定“真解锁”不能只看 left 值
仅检查 slider.style.left >= trackWidth - thumbWidth 极易误判:手指抬离位置偏移、快速拖拽惯性、触摸精度误差都会导致假成功。
- 应在
touchend或mouseup触发时,计算总位移deltaX = currentX - startX - 要求
deltaX >= trackWidth - thumbWidth - 10(留 10px 容差)且deltaX > 0(确保从左到右) - 加简单防抖:记录上次
touchend时间戳,若距当前不足 100ms 则忽略本次 - 成功后立刻置灰容器、移除所有事件监听器,否则多次绑定会导致重复触发
视觉反馈和防绕过要点
滑块到位 ≠ 解锁完成。攻击者可直接调用 unlock() 或篡改 DOM,前端状态不可信。
- 解锁成功回调里不要直接开放敏感操作,应发起一次轻量 POST 请求(如
/verify-unlock),带时间戳 + 简单签名,服务端校验distance和duration是否在合理区间 -
localStorage.setItem('unlocked', 'true')必须带时效(如 5 分钟 TTL),且服务端绝不信任该字段 - 失败反馈用
transform: scale(0.95)+ 文字提示,比弹窗更轻量;成功后销毁 canvas 或清空容器innerHTML,不留静态可分析痕迹 - 滑块区域不能设
pointer-events: none—— 这会让touchstart根本不触发;只对非交互层(如背景遮罩)设该样式
真正难的不是拖动动画,而是让“用户确实完成了动作”这件事在 JS 层有可信证据:位移、方向、持续时间、释放时机,四者缺一不可;任何一项靠 DOM 属性或 CSS 类名推断,都会被轻易绕过。
前端入门到VUE实战笔记:立即使用
在学习笔记中,你将探索 前端 的入门与实战技巧!











