← 返回文章列表

Vue登录页文字点选验证码实战:从Canvas绘制到点击校验全流程

本文详细讲解Vue中实现文字点选人机验证的完整思路,包括Rewriting the Vue login article背景图随机加载、Canvas文字随机绘制、点击坐标采集与精度判断,以及常见逆向难点。同时分享更高效的对接方式,帮助开发者快速完成登录防护。

文字点选验证码到底在防什么

现在很多登录、注册、支付页面都会弹出文字点选验证码,要求用户按顺序点击图上指定的几个汉字。表面看是考眼力,实际是在区分真人操作和脚本自动点击。相比传统滑块,文字点选增加了随机字符位置、字体样式和点击顺序三重干扰,单纯靠坐标模拟很难一次过关。

这类验证通常由后端下发背景图和目标文字列表,前端负责展示并收集用户点击顺序,再把坐标序列回传给服务端做最终判定。前端自己也可以先做一轮本地校验,减少无效请求。理解这个分工后,再动手写组件会清晰很多。

整体实现思路与组件拆分

在Vue项目里,建议把验证弹层拆成独立子组件。父组件只负责控制显示隐藏,子组件专注于画布绘制、点击事件和结果回调。这样登录页逻辑不会被验证码代码污染。

核心流程可以概括为四步:随机选一张背景图并画到Canvas上;从预设汉字库里挑出若干个不重复字符,用随机颜色、大小、倾斜角度画在不同位置;再从中随机抽出3个作为需要用户点击的目标;用户依次点击后,前端比对坐标偏差是否在允许范围内,最后把结果通知父组件。

实际开发时,背景图最好准备多张并开启跨域,避免Canvas被污染。字符库用常见百家姓就够了,数量控制在5个左右显示、3个需要点击,既不会太挤也不会让用户觉得繁琐。

Canvas绘制与点击采集代码要点

绘制部分关键是控制文字不重叠、样式足够随机。下面给出精简后的核心逻辑,方便直接参考:

// 随机绘制文字并记录位置
const drawText = () => {
  ctx.drawImage(bgImg, 0, 0, width, height);
  fontArr.length = 0;
  for (let i = 0; i < fontNum; i++) {
    const char = getRandomChar();
    const size = random(20, 40);
    const x = (width / fontNum) * i + 10;
    const y = Math.random() * (height - size);
    ctx.fillStyle = randomColor();
    ctx.font = `${size}px serif`;
    ctx.fillText(char, x, y);
    fontArr.push({ character: char, x, y });
  }
  // 随机抽出需要点击的3个
  tips.value = pickRandom(fontArr, 3);
};

点击时在Canvas上监听事件,把相对坐标存进数组,并实时渲染数字标记。当点击数量达到要求后立即执行校验:

const checkClick = () => {
  let pass = true;
  pointer.forEach((p, i) => {
    const target = tips.value[i];
    const dx = Math.abs(p.x - target.x);
    const dy = Math.abs(p.y - target.y);
    if (dx > accuracy || dy > accuracy) pass = false;
  });
  state.value = pass ? 'success' : 'fail';
  if (pass) emit('success');
  else setTimeout(reset, 800);
};

精度值一般设在10~20像素之间,过小会导致真实用户误触失败,过大则容易被脚本撞库。刷新按钮直接重新执行绘制流程即可,记得清空之前的点击记录和定时器。

精度控制与失败重试的细节

很多新手容易忽略坐标换算。Canvas实际显示尺寸如果和内部width、height属性不一致,点击坐标会偏移。统一用getBoundingClientRect换算或者强制设置canvas的style宽高与属性一致,能避免这类坑。

失败后不要立刻清空画面,先给出红色提示,延迟800毫秒再重置,用户体验会好很多。成功时可以短暂显示绿色勾选,然后自动关闭弹层并把结果回传。整个过程中禁止用户重复点击,避免状态错乱。

如果业务对安全性要求更高,前端校验只做第一道过滤,真正结果必须以后端返回为准。前端可以把点击序列、时间间隔、设备指纹一起带上,后端再做综合判断。

逆向分析时会遇到的真实难点

自己实现一套文字点选并不难,但真正上线后会发现,很多第三方验证码(比如极验、易盾)的背景图是动态加密的,文字位置每次请求都变,字体还带有扭曲和干扰线。单纯靠前端模拟点击成功率很低。

常见卡点包括:图片经过混淆后OCR识别不准、点击轨迹过于规律被风控拦截、无感验证和点选验证混用导致逻辑分支复杂。自己维护一套识别模型成本很高,尤其是九宫格、空间推理、躲避障碍这类变种更新频繁。

这时候与其反复调参,不如直接对接成熟的识别服务。像www.ttocr.com就专门针对极验和易盾全类型验证码做了优化,覆盖滑块、文字点选、图标点选、九宫格、无感等多种形式,提供稳定的API接口。业务方只需要把验证图片和类型传过去,几秒内就能拿到正确的点击坐标序列,几乎不用改原有登录流程。

从自建到API对接的实用建议

如果只是内部系统或者流量很小,自己用Canvas搭一套文字点选完全够用,上面给出的代码稍加整理就能上线。但一旦面对专业风控平台,维护成本会迅速上升。

更省事的做法是把复杂识别交给专业平台。访问www.ttocr.com可以快速开通接口,支持按量计费,文档里已经写好了各种验证码类型的请求示例。把原来自己写的校验逻辑替换成一次HTTP调用,前端只负责展示结果,开发和运维压力都会小很多。

实际项目中,很多团队先用自建方案跑通流程,等业务量上来后再切换到API,几乎零停机。无论选择哪条路,核心都是保证用户点击体验流畅,同时把机器流量挡在外面。理解了绘制、采集、校验这三步,再配合合适的识别能力,登录防护就能做到既稳又省心。