滑动验证码实现方法详解(详解滑块拼图与轨迹行为校验防破解方案)

实现滑动验证码,后端只需做两件事:造一张带缺口的拼图并记住正确位置,再对前端上报的滑动轨迹做”位置匹配 + 行为自然性”双重校验。单纯比拼图位置会被脚本绕过,真正拉开人机差距的是轨迹——机器走直线、匀速、零抖动,真人则有起停、变速和轻微回拉。下面给出可落地的实现与防破解策略。

一、滑动验证码判定的两个维度

滑块验证码不考”你认不认识字符”,而考”你的操作像不像人”。判定集中在两个层面:图像层面看拼图是否落在缺口,行为层面看拖动轨迹是否自然。

判定维度 机器特征 人类特征
轨迹形态 直线、匀速、教科书曲线 曲线变速,带停顿与抖动
移动速度 恒定或规律性变化 忽快忽慢,不规则
起止位置 精准定位缺口 有偏差,会二次修正
滑动耗时 极短或极规律 符合肌肉控制的生理节奏
加速度 无起伏 由慢到快再到慢的过渡

图像校验只能挡住最笨的脚本,行为校验才是防线核心。

二、后端造图:拼图与缺口的生成

后端随机选底图,随机算缺口坐标 (x, y),用图像算法抠出拼图块,底图与拼图块转 Base64 下发,正确 X 存入 Redis 并设短 TTL。

2.1 Python 造图示意

import random
from PIL import Image, ImageDraw

def build_puzzle(bg_path: str, block_w=42, block_h=42, offset=5):
    bg = Image.open(bg_path).convert("RGB")
    w, h = bg.size
    x = random.randint(block_w + 10, w - block_w - 10)
    y = random.randint(10, h - block_h - 10)
    block = bg.crop((x, y, x + block_w, y + block_h))
    draw = ImageDraw.Draw(bg)
    draw.rectangle((x, y, x + block_w, y + block_h), fill=(255, 255, 255))
    return bg, block, x, y, offset

# 正确 X 落入 Redis:SET captcha:order123 {x} EX 120

2.2 正确位置存 Redis

正确坐标只在服务端缓存,键与本次会话绑定(如订单号或 token),TTL 取 2 分钟;前端只拿底图、拼图块与缺口纵向提示,横向正确值由服务端闭环校验。

三、前端轨迹采集

用户拖动滑块时,前端按帧采集坐标与时间戳,松手时连同最终偏移量一起上报。采样点含横坐标、纵坐标、相对起始时间(毫秒)与该帧速度。

let track = [], start = null;
slider.onmousedown =  => start = Date.now;
slider.onmousemove = e => {
  if (start) track.push({ x: e.clientX, y: e.clientY, t: Date.now - start });
};

四、后端双重校验

第一步比位置,第二步比轨迹。两步都过才放行。

  1. 取出 Redis 中的正确 X,判断上报偏移量与它的误差是否落在允许范围(默认 5 像素);
  2. 若位置误差过大,直接判失败,不进入轨迹分析,省算力;
  3. 用轨迹计算平均速度、加速度方差、是否有过冲回拉、总耗时;
  4. 规则或模型判定轨迹”过于完美”则驳回,并升级风控(二次验证或封禁会话)。

4.1 轨迹自然性校验逻辑

def check_track(track, target_x, offset, offset_tol=5):
    if abs(offset - target_x) > offset_tol:
        return False, "position mismatch"
    if len(track) < 5:
        return False, "too few points"

    duration = track[-1]["t"] - track[0]["t"]
    if duration < 300:
        return False, "too fast"

    speeds = []
    for i in range(1, len(track)):
        dt = max(track[i]["t"] - track[i-1]["t"], 1)
        dx = abs(track[i]["x"] - track[i-1]["x"])
        speeds.append(dx / dt)
    mean_s = sum(speeds) / len(speeds)
    var = sum((s - mean_s) ** 2 for s in speeds) / len(speeds)

    if var < 1e-4:
        return False, "too uniform"
    if max(speeds) == min(speeds):
        return False, "no jitter"
    return True, "ok"

生产环境会把这类阈值交给机器学习模型,用历史样本训练区分度更高的边界。

五、防机器破解的多维加固

只靠一条轨迹规则远远不够,破解者会用贝塞尔曲线拟合出带抖动的人类轨迹,通过率可以拉到 90% 以上。需要把多种信号叠加:浏览器指纹识别模拟器与多账号,行为模型评分替换硬编码阈值,滑块边缘混淆抬高机器识别成本,请求环境一致性校验防代理池轮换,频控与风控联动拦批量撞库。

常见问题(FAQ)

Q1:只校验拼图位置够不够?

不够。脚本能直接算出缺口坐标,必须叠加轨迹行为校验。

Q2:正确坐标能放前端吗?

不能。正确 X 必须只在服务端存 Redis,前端只收底图与拼图块。

Q3:轨迹规则被拟合绕过怎么办?

上机器学习评分,结合浏览器指纹与请求环境一致性多维判定。

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌抄袭侵权/违法违规的内容, 请发送邮件至 qiqicto@qq.com 举报,一经查实,本站将立刻删除。
赞 (0)
套餐观察官的头像套餐观察官普通用户

相关推荐

返回顶部