验证码组件
四种纯前端交互验证码:滑块(拖到头通过)、旋转(拖滑块把图片转正)、拼图滑块(拖滑块对齐缺口)、点选(按序点击图中文字)。零第三方依赖,样式走 @fx/styles 设计 token(亮暗主题自动跟随)。
组件只负责人机交互与通过判定,服务端强校验由消费方接线:滑块/旋转/拼图通过 success 事件拿到用时,点选通过 confirm 事件拿到坐标序列(序号 + 像素坐标 + 时间戳)。
组件已随 @fx/components 提供(web 已内置依赖),无需单独安装。
vue
<script setup lang="ts">
import { FxCaptchaSlider } from "@fx/components"
const passed = ref(false)
</script>
<template>
<FxCaptchaSlider v-model="passed" />
</template>组件一览
| 组件 | 交互 | 典型场景 |
|---|---|---|
| FxCaptchaSlider | 按住滑块拖到最右端 | 登录/注册表单门控(基座组件,可 isSlot 组合) |
| FxCaptchaRotate | 拖滑块把随机预旋转的圆图转正 | 图片类风控验证 |
| FxCaptchaPuzzle | 拖滑块把拼图块对齐缺口 | 图片类风控验证 |
| FxCaptchaPointSelect | 按提示依次点击图中文字位置 | 文字点选风控验证 |
与后端对接
组件只负责前端交互,完整的安全闭环由服务端三步完成:
text
① 获取题目 GET /captcha?type=puzzle
服务端生成题目,答案写入 Redis(captcha:{id},TTL 2~5 分钟,一次性)
└─ 返回 captchaId + 题目数据(图片 URL / 角度 / 坐标)
② 前端交互 组件完成拖动/点选(答案类 props 接服务端下发数据)
③ 提交校验 业务请求附带 captchaId + 交互结果
服务端取答案做容差判定 → 销毁 → 返回结果各类型的服务端数据
| 类型 | ① 下发给组件 | 服务端留存 | ③ 校验口径 |
|---|---|---|---|
| 滑块 | 无(纯交互门控) | 无 | 前端判定即可;可加用时/轨迹合理性复验 |
| 旋转 | 图片 URL + answer-degree | answerDegree 随机角 | 用户停止角与答案差 ≤ diffDegree(默认 20°) |
| 拼图 | 背景图 URL + answer-x | answerX 缺口横坐标 | 用户停留 x 与答案差 ≤ diffDistance(默认 3px) |
| 点选 | 服务端渲染的目标字+干扰字图片 | 目标字坐标数组(按序) | 点击数一致,且第 i 次点击落在第 i 个目标字容差框内(建议半径 8~12px) |
旋转/拼图通过 answer-degree / answer-x props 接收服务端答案(提供时跳过本地随机)——组件本地的 Math.random 仅适用于无服务端的演示场景。
安全要点
- 答案只存服务端:旋转的角度、拼图的缺口坐标、点选的目标字位置都不应明文下发;接服务端校验后把容差判定整体移到服务端(组件侧仅作体验提示)
captchaId一次性消费(校验即销毁)+ 短 TTL + 连续失败 N 次作废,防重放与爆破- 点选图片由服务端渲染(目标字+干扰字+干扰线/扭曲),前端坐标按图片原始尺寸做比例换算
- 滑块建议校验
success事件抛出的拖动用时与轨迹合理性(匀速直线多为脚本)
注意事项
- 拼图组件用 canvas 从图片取像,图片源需允许跨域(
crossOrigin="anonymous",如 picsum 等 CDN) - 点选组件的坐标为图片容器内像素坐标,服务端校验时注意按图片原始尺寸做比例换算