Vue 验证码前后端分离怎么接?滑块回调与服务端校验示例
Vue 滑块显示成功后,后端还要做什么?用不墨验证码演示产品 ID、API KEY、captchaId 的分工,提供 Vue 3 组件、Node.js 校验函数和失败处理检查单。

Vue 接滑动验证码,最容易漏掉的是前端成功回调之后的服务端校验。组件变绿只代表拿到了一个待校验凭证;业务后端确认凭证通过,才可以执行受保护的操作。
下面以 Vue 3 和不墨行为式验证码为例。前端只负责展示、收集凭证、提交请求;API KEY 始终留在后端。示例是接入骨架,业务接口需要接到你已有的服务里,不是完整注册系统。
先分清三个值
- 产品 ID:前端初始化 SDK 用,也用于服务端请求的
x-id。从产品控制台取得。 - API KEY:后端调用校验服务的凭据。不要放进 Vue 的源码、
VITE_环境变量或浏览器请求。 - captchaId:每次滑动成功回调得到的值,前端随本次业务请求提交给后端,放在校验请求体的
r字段里。
开通产品、创建验证码 API KEY,并将实际使用的域名加入白名单。后端 referer 使用白名单中的业务站点地址,不要照抄示例域名。字段与接口以官方 API 文档为准。
第一步:加载 SDK,再挂载 Vue
对于普通 Vue + Vite 单页应用,把下面脚本放在 index.html 的 Vue 入口脚本之前,确保组件挂载时 SDK 已经可用:
<script src="https://cdn.bumo.cc/apps/captcha-sdk/captcha.js"></script>
<script type="module" src="/src/main.js"></script>
这是最直观的加载顺序,外部脚本会阻塞后面的解析。需要异步加载时,应在脚本的 load 回调后初始化,不能只加 async 然后照常读取 window.BumoCaptcha。SSR 项目则要把 SDK 加载和初始化放到浏览器端执行。
第二步:在 Vue 3 组件里传递凭证
把 YOUR_PRODUCT_ID 替换成控制台给出的产品 ID。示例假设此组件在页面上只挂载一次;同页多个组件需要使用不同容器 ID。
<script setup>
import { onMounted, ref } from 'vue';
const captchaId = ref('');
const busy = ref(false);
const message = ref('');
let captcha;
onMounted(() => {
if (!window.BumoCaptcha) {
message.value = '验证组件加载失败,请刷新重试';
return;
}
captcha = new window.BumoCaptcha({
containerId: 'BUMO_CAPTCHA',
id: 'YOUR_PRODUCT_ID',
successCallback: (id) => { captchaId.value = id; },
failCallback: () => { captchaId.value = ''; },
});
});
async function submit() {
if (!captchaId.value || busy.value) return;
busy.value = true;
message.value = '';
try {
const response = await fetch('/api/protected-action', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ captchaId: captchaId.value }),
});
if (!response.ok) throw new Error('请求未完成,请重新验证后重试');
message.value = '操作已完成';
} catch (error) {
message.value = error.message;
} finally {
captchaId.value = '';
captcha?.reset();
busy.value = false;
}
}
</script>
<template>
<div id="BUMO_CAPTCHA"></div>
<button :disabled="!captchaId || busy" @click="submit">
{{ busy ? '提交中…' : '提交' }}
</button>
<p role="status">{{ message }}</p>
</template>
/api/protected-action 是你的业务接口,不是验证码平台的地址。如果前后端不同域名,需要在你自己的后端配置允许的跨域来源;涉及登录 Cookie 时,也要沿用应用原有的凭据和 CSRF 防护方案。不要为了让请求通过而开放任意来源。
提交结束后清空凭证并重置滑块,避免用户误把上一次的成功状态当成本次验证。按钮禁用用于减少重复点击,后端仍需自行保证业务幂等与限频。
第三步:Node.js 后端确认结果
下面函数使用支持全局 fetch 和 AbortSignal.timeout 的 Node.js 运行环境。三个环境变量仅在服务端设置:BUMO_CAPTCHA_API_KEY、BUMO_CAPTCHA_PRODUCT_ID、APP_ORIGIN。
export async function verifyCaptcha(captchaId) {
if (typeof captchaId !== 'string' || !captchaId.trim()) return false;
const key = process.env.BUMO_CAPTCHA_API_KEY;
const productId = process.env.BUMO_CAPTCHA_PRODUCT_ID;
const origin = process.env.APP_ORIGIN;
if (!key || !productId || !origin) {
throw new Error('验证码服务端配置不完整');
}
try {
const response = await fetch(
'https://captcha.bumo.cc/api/captcha/server/get-result',
{
method: 'POST',
headers: {
'Content-Type': 'application/json',
authorization: `Bearer ${key}`,
referer: origin,
'x-id': productId,
},
body: JSON.stringify({ r: captchaId }),
signal: AbortSignal.timeout(10000),
},
);
if (!response.ok) return false;
const result = await response.json();
return result.success === true && result.data?.p === true;
} catch {
return false;
}
}
在现有业务路由中先 await verifyCaptcha(requestBody.captchaId);结果为 false 时返回失败,只有 true 才进入业务操作。不要仅检查 HTTP 200,也不要只检查 JSON 的 success,检测是否通过还要看 data.p。
本例采用失败时拒绝的策略:网络超时、限流、异常响应都不放行。官方快速开始另有偏向可用性的降级示例,两者是不同的取舍。涉及收费资源、发短信或高风险操作时,不应把服务故障直接当作验证通过;应给用户明确重试入口,并由团队根据业务风险设计降级策略。
上线前用这五项验收
- 正常滑动后提交,后端确实调用校验服务,并在通过后才执行业务。
- 绕过页面,直接发送空
captchaId,业务操作不能执行。 - 校验返回
success: true但data.p: false,必须拒绝。 - 测试环境模拟校验超时或非 JSON 响应,页面可重试,后端不能自动放行。
- 浏览器源码与 Network 中找不到 API KEY,反复提交后滑块状态会重置。
本文代码已做本地模拟响应检查,未用真实付费凭据完成线上业务联调。接入后仍需用自己的产品 ID、白名单域名和后端 API KEY 跑通一次真实验证。
如果你还在判断验证码适合放在哪个入口,可以继续看注册防刷的处理顺序。已有 Vue 页面则可以从开通验证码试用开始,把前端回调和服务端校验接成一条完整链路。


