产品介绍V2.2
简介#
云智安全验证是一套智能无感验证平台,结合设备指纹、行为特征、访问频率、地理位置等多项技术,有效拦截恶意登录、批量注册,阻断机器操作。较传统验证码相比,用户无需再经过思考或输入操作,只需轻轻一滑即可完成验证;经过智能鉴别为正常的用户,在一定时间内无需再进行滑动操作,既为企业提供了安全保障,也让用户无感知通过,极大提升用户体验。平台支持 Web 端与移动端 H5,前端组件已针对触屏设备做适配(Touch 事件与设备像素比自动处理),接入只需「引入组件 → 初始化 → 服务端二次校验」三步。
产品特点
- 精准识别:行为特征结合智能策略模型,覆盖速度分布、轨迹形态、加速度特征、时间规律、轨迹熵值与操作延迟等多维深度校验,精准判定人机操作;
- 图像对抗:验证图融合多重随机视觉干扰与动态扰动处理,滑块拼图与背景噪声同源化、凹槽亮度均衡、全局边缘噪声对抗与拼图片边缘羽化,点选字符与背景色彩自然融合并混入形近干扰字,显著提高 OCR / 模板匹配 / 边缘检测类 CV 攻击成本;
- 动态风控:行为判定阈值随会话风险等级与请求压力动态调整,越可疑越严格;
- 极致体验:依托全球 50+ 加速节点,服务毫秒级响应;
- 布局美观:弹窗、嵌入等多种形态,适用于各种业务场景,覆盖电脑、手机全平台;
- 快速接入:前端组件快速接入,仅需三步轻松搞定;
- 数据可视化:用户中心提供额度概览,防御拦截数据尽收眼底。
应用场景#
智能无感验证产品可应用于任何需要验证的业务场景,包括但不限于:
- 账号类:注册、登录、修改密码、修改邮箱、修改手机号等敏感操作前置人机验证,拦截批量注册与撞库攻击;
- 活动类:红包福利领取、竞猜答题、积分兑换、限时抢购,防止机器刷单薅羊毛;
- UGC 类:发帖、评论、点赞、投票,遏制垃圾内容与刷量行为;
- 辅助验证类:短信验证码、邮箱验证码发送前的前置校验,避免短信通道被恶意消耗。
接入流程#
整体交互时序如下,核心原则是:前端拿 token,服务端做最终裁决。
- 页面引入 captcha.css 与 captcha.js,调用
YzCaptcha.create嵌入验证组件; - 用户触发验证,完成点击 / 滑块 / 旋转交互;
- 验证通过后,前端通过
onSuccess回调获得一次性 token; - 前端将 token 随业务表单一起提交到您的业务服务端;
- 业务服务端携带
appId、appSecret、token调用 tokenVerify 接口二次校验; - 校验通过则放行业务流程,失败则拒绝并提示用户重新验证。
action=get 响应 data 中包含 challengeId(服务端挑战存储标识,已绑定签发端 IP/UA,泄露后无法在他环境使用),action=check 时随表单原样回传即可——官方组件已自动处理,跨站接入不再依赖第三方 Cookie;若您自行封装请求,请务必携带该字段,未携带时系统回退到 PHP 会话绑定(仅同源场景可靠)。挑战有效期 180 秒,单挑战最多尝试 5 次,验证通过、达到尝试上限或过期后即销毁。action=get 获取挑战免费(受限流保护),仅 action=check 验证通过时扣减 1 次额度并签发 token,验证失败不扣费。AppID 公开于前端属正常现象,泄露不再导致额度被恶意消耗。接入排错指引
接入或联调过程中遇到异常时,建议按以下顺序逐项排查,大多数问题可在前几步定位:
- 确认接口可达:在业务服务器上请求一次
https://safe.yunzhiapi.cn/api/captcha.php,能返回 JSON(即使是参数错误)即说明网络连通;浏览器开发者工具 Network 面板确认 get / check 请求已发出、未被跨域或混合内容拦截; - 核对 AppID:确认前端传入的 appId 与用户中心「API 凭证」完全一致(32 位,无首尾空格与换行),不一致会返回 40101;
- 查看浏览器控制台:组件脚本加载失败、挂载容器不存在、回调拼写错误等问题都会在 Console 留下直接线索;
- 核对 challengeId 回传:自研封装时确认 check 请求体原样携带了 get 返回的 challengeId;缺失时仅同源会话场景可用,跨站场景必然返回 410;
- 区分错误码来源:5 位错误码(如 40103、42901)来自 API 层,3 位错误码(如 403、410)来自引擎校验层,按下文错误码表对号入座,不要混淆排查方向;
- 仍无法定位:记录错误码、请求时间点与 appId,查阅常见问题或联系技术支持。
Web/H5 初始化配置#
引入组件样式与脚本,传入 appId 与 apiServer 即可完成接入;验证模式由用户中心统一配置,前端无需关心挑战类型(组件会根据服务端返回自动渲染点选 / 滑块 / 旋转界面)。最快三步上手:
<link rel="stylesheet" href="https://safe.yunzhiapi.cn/validate/pack.php?f=css">
<script src="https://safe.yunzhiapi.cn/validate/pack.php?f=js"></script>
<div id="cap"></div>
<script>
var cap = YzCaptcha.create({
el: document.getElementById('cap'),
appId: '你的AppID',
apiServer: 'https://safe.yunzhiapi.cn',
success: function (token) {
// 验证通过,token 随业务表单提交
},
fail: function (msg) {
// 验证失败回调(可选)
}
});
</script>
https://safe.yunzhiapi.cn/validate/captcha.php(会话制、不计费,不签发正式 token,仅返回一次性会话凭证),通过 api 参数传入即可。YzCaptcha.create 参数表
| 参数 | 类型 | 必填 | 说明 |
|---|---|---|---|
el | Element | 是 | 挂载容器元素,组件按钮将渲染到该元素内 |
appId | string | 是 | 应用 ID(32 位),在用户中心「API 凭证」中获取 |
apiServer | string | 否 | 验证服务地址,填本站根地址 https://safe.yunzhiapi.cn;不传时默认同源 |
api | string | 否 | 完整接口地址(高级参数,与 appId/apiServer 二选一)。正式接入为 https://safe.yunzhiapi.cn/api/captcha.php?appId=你的AppID;演示环境可用 https://safe.yunzhiapi.cn/validate/captcha.php(会话制,不计费,不签发正式 token) |
type | string | 否 | 指定验证模式 click/slide/rotate。正式接入建议省略:由用户中心配置决定,组件按服务端返回自动渲染 |
width | number | 否 | 验证弹窗宽度(260~480px),默认 400px(小屏设备自动自适应) |
allowedOrigins | string[] | 否 | 脚本来源白名单(如 ['https://cdn.example.com']):用于校验 captcha.js 的加载来源是否可信,防范 CDN 篡改注入风险 |
success | function(token) | 是 | 验证通过回调,参数为一次性 token(同 onSuccess,二者等价任选其一) |
fail | function(msg) | 否 | 验证失败回调,参数为失败原因(同 onFail) |
onCancel | function() | 否 | 用户取消验证回调(同 cancel) |
success/onSuccess、fail/onFail、onCancel/cancel,同时传入时优先使用 onXxx 形式。组件内置失败自动刷新、410 挑战过期自动重领、15 秒请求超时与触屏适配,无需额外处理。接口字段说明(自研封装时参考)
官方组件已自动处理以下字段,仅在您不使用 captcha.js、自行调用接口时需要关注:
| 字段 | 位置 | 说明 |
|---|---|---|
type | get 响应 data | 挑战类型(click/slide/rotate),由用户中心配置决定 |
challengeId | get 响应 data | 服务端挑战标识(32 位十六进制),check 时必须原样回传 |
img / piece / tipImg / y | get 响应 data | 挑战素材:底图(dataURI)、滑块拼图块、点选提示图(dataURI,V2 起不再下发明文提示字)、拼图纵向位置 |
quota | check 成功响应 data | 验证通过扣费后的剩余接口额度(V2 起 get 免费,不再返回该字段) |
challengeId | check 请求体 | 回传 get 获得的挑战标识;缺失时回退会话绑定(跨站场景会失败) |
points / x / angle+flipH+flipV | check 请求体 | 三种模式各自的答案字段 |
meta | check 请求体 | 行为特征数据(JSON,含 dur/ft/moves/wd/touch/risk 字段),由官方组件自动采集上报,自研封装时需按组件行为构造 |
token | check 成功响应 data | 一次性安全凭据,300 秒内由服务端 tokenVerify 消费 |
三种验证模式差异
- click(点击验证):按提示顺序点击图中的目标文字,采用动态容差并校验点击顺序;目标文字逐字采用不同字号与随机倾角,字符颜色采样自背景局部并自然融合,图中同时混入与目标字形近、但未出现在提示中的干扰文字,交互最轻,适合登录、评论等高频场景;
- slide(滑块验证):拖动滑块将拼图移动至相同形状的凹槽处。凹槽形状每次随机生成,并配有多个外观完全同源的干扰凹槽;拼图块与背景经过噪声同源化与边缘羽化处理,凹槽内部做亮度均衡纹理填充,全图叠加边缘噪声对抗,机器定位与像素比对类攻击难以区分真实目标,适合注册、表单提交场景;
- rotate(旋转验证):图片随机旋转任意角度并可能叠加水平 / 垂直镜像翻转,用户需先点击翻转按钮还原镜像、再拖动滑块旋转至正确方向,解空间最大,适合抢购、领券等高风险场景。
最佳实践
- 为脚本与样式配置 SRI 完整性校验:防止 CDN 或中间环节篡改组件文件,示例:
<link rel="stylesheet" href="https://safe.yunzhiapi.cn/validate/pack.php?f=css"
integrity="sha384-实际哈希值" crossorigin="anonymous">
<script src="https://safe.yunzhiapi.cn/validate/pack.php?f=js"
integrity="sha384-实际哈希值" crossorigin="anonymous"></script>
- 如同时配置了
allowedOrigins白名单,请将承载组件文件的来源域名一并加入; - token 通过表单隐藏域提交:在
success回调中把 token 写入<input type="hidden">随表单 POST 到业务服务端,不要拼接到 URL 或放入全局变量长期持有(参考下文「前端集成示例」); - 失败重试策略:验证失败与挑战过期(410)的自动刷新已由组件内置,无需自行实现;业务服务端收到 40103 时应引导用户重新验证而非重放旧 token,收到 42901 时采用指数退避间隔重试;
- 正式接入省略
type参数:验证模式交由用户中心统一配置,便于后续按业务风险灵活调整而无需改动前端代码。
接入检查清单
上线前请逐项确认:
- 页面已正确引入组件样式与脚本(
pack.php?f=css与pack.php?f=js,组件经服务端加密分发、内置解密输出),资源加载无 404; appId填写正确(32 位,无首尾空格),apiServer指向本站地址;success/onSuccess回调中能够拿到 token,并已写入表单隐藏域随业务请求提交;- 业务服务端已接入 tokenVerify 二次校验,并对 40103 / 40201 / 42901 等错误码有明确处理分支;
- 模拟挑战过期场景(停留超时后提交),确认组件在收到 410 后自动刷新验证、用户无感;
- AppSecret 仅保存在服务端,未出现在前端代码与版本仓库中;
- 已在 Chrome、Safari 及移动端真实设备上各跑通一次完整验证流程。
前端集成示例#
以登录表单为例:用户必须先通过人机验证,提交按钮才可用,token 随表单一起 POST 到业务后端:
<form id="loginForm" method="post" action="/login">
<input type="text" name="username" placeholder="用户名" required>
<input type="password" name="password" placeholder="密码" required>
<div id="cap"></div>
<input type="hidden" name="captcha_token" id="captchaToken">
<button type="submit" id="submitBtn" disabled>登录</button>
</form>
<script>
var submitBtn = document.getElementById('submitBtn');
YzCaptcha.create({
el: document.getElementById('cap'),
appId: '你的AppID',
apiServer: 'https://safe.yunzhiapi.cn',
success: function (token) {
document.getElementById('captchaToken').value = token;
submitBtn.disabled = false;
},
onCancel: function () {
submitBtn.disabled = true;
}
});
</script>
tokenVerify 二次校验(PHP 完整示例)#
业务服务端收到表单后,必须调用 tokenVerify 接口做最终校验。以下函数可直接复制使用(已填入本站服务地址):
/**
* 服务端 token 二次校验
* @param string $appId 应用ID(32位)
* @param string $appSecret 应用密钥(64位,仅保存在服务端)
* @param string $token 前端提交的一次性 token
* @return array ['pass' => bool, 'code' => int, 'message' => string]
*/
function verifyCaptchaToken($appId, $appSecret, $token) {
$url = 'https://safe.yunzhiapi.cn/api/token_verify.php';
$postFields = http_build_query([
'appId' => $appId,
'appSecret' => $appSecret,
'token' => $token,
]);
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, $url);
curl_setopt($ch, CURLOPT_POST, true);
curl_setopt($ch, CURLOPT_POSTFIELDS, $postFields);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, 3); // 连接超时 3 秒
curl_setopt($ch, CURLOPT_TIMEOUT, 5); // 整体超时 5 秒
$body = curl_exec($ch);
$errno = curl_errno($ch);
curl_close($ch);
// 网络异常容错:按业务风险策略决定放行或拒绝,此处选择拒绝
if ($errno !== 0 || $body === false) {
return ['pass' => false, 'code' => -1, 'message' => '验证服务网络异常,请稍后重试'];
}
$data = json_decode($body, true);
if (!is_array($data) || !isset($data['data']['serverStatus'])) {
return ['pass' => false, 'code' => -2, 'message' => '验证服务响应格式异常'];
}
// data.serverStatus=SERVER_SUCCESS 且 data.result=true 表示校验通过
$payload = $data['data'];
$pass = $payload['serverStatus'] === 'SERVER_SUCCESS' && !empty($payload['result']);
$code = isset($data['code']) ? (int)$data['code'] : 0;
$msg = $pass ? 'ok' : (isset($payload['error']['reason']) ? $payload['error']['reason'] : '校验未通过');
// 错误码分支处理示例
if (!$pass) {
switch ($code) {
case 40103: $msg = '验证已过期,请重新验证'; break;
case 40201: $msg = '账户额度不足,请联系管理员充值'; break;
case 42901: $msg = '请求过于频繁,请稍后再试'; break;
}
}
return ['pass' => $pass, 'code' => $code, 'message' => $msg];
}
tokenVerify 响应结构
校验结果位于响应 data 内:serverStatus 表示接口调用状态(SERVER_SUCCESS / SERVER_FAILED),result 表示业务校验结论:
// 校验通过
{"code":200,"msg":"校验通过","data":{"serverStatus":"SERVER_SUCCESS","result":true}}
// 校验未通过(token 失效/已消费/不匹配)
{"code":40103,"msg":"验证 token 无效或已过期","data":{"serverStatus":"SERVER_SUCCESS","result":false,
"error":{"code":40103,"reason":"验证 token 无效或已过期","advice":"token 有效期 300 秒且一次性,请重新发起验证"}}}
// 凭证类错误(AppID / AppSecret 无效、缺参等)
{"code":40102,"msg":"凭证无效:AppSecret 校验失败","data":{"serverStatus":"SERVER_FAILED","result":false,
"error":{"code":40102,"reason":"凭证无效:AppSecret 校验失败","advice":"请核对 AppSecret,泄露时请在用户中心重置"}}}
安全建议
- AppSecret 只能保存在服务端,严禁出现在前端代码、App 安装包或版本仓库中,泄露后请立即在用户中心重置;
- token 一次性使用,服务端校验成功后即作废,任何重放都会返回 40103;
- 建议对 tokenVerify 调用设置 3~5 秒超时,并对网络异常有明确的降级策略;
- tokenVerify 必须 POST 请求,参数为
appId、appSecret、token(可选userIp上送终端用户 IP 附加绑定校验),勿拼接到 URL 中以免进入日志。
安全能力说明#
V2.2 引擎针对自动化识别、轨迹伪造、重放盗用等常见攻击手段构建了体系化防护,主要能力概述如下:
- 多层图像对抗:验证图融合多种随机视觉干扰与动态扰动处理,人眼几乎无感,但显著提高 OCR、模板匹配、边缘检测等自动化识别技术的攻击成本;
- 滑块同源对抗(V2.2 增强):拼图块与背景图像做噪声同源化处理,二者统计特性完全一致;凹槽内部以同亮度随机纹理填充消除亮度差异;全图叠加同族边缘噪声淹没凹槽轮廓梯度;拼图块边缘做渐变羽化模糊形状边界——像素比对、亮度检测、边缘检测与形状识别类定位手段无法区分真实凹槽与干扰凹槽;
- 点选视觉融合(V2.2 增强):目标文字逐字采用不同字号与随机倾角,字符颜色采样自背景局部区域并自然融合,背景中混入未出现在提示内的形近干扰文字,显著降低 OCR 识别与粗定位的可用性;
- 多维行为模型:基于操作过程的多维行为特征模型进行综合人机判定,而非仅校验答案本身;V2.2 起行为轨迹深度校验覆盖速度变异、轨迹直线度、加速度分布、时间戳规律与抖动、轨迹熵值及首操作延迟等维度,可有效识别脚本模拟、插值拼接与轨迹伪造;
- 动态风控引擎:结合会话风险、环境信誉与访问压力实时评估风险等级,动态调节挑战强度与判定策略——越可疑越严格,正常用户无感通过;
- 挑战一次性与环境绑定:每次挑战唯一、限时有效、一次性使用,并与签发环境绑定,防止挑战被重放或跨环境盗用;
- token 服务端存储:验证 token 由服务端存储与管理,一次性使用、限时有效,校验成功即销毁,任何伪造与重放均无法通过 tokenVerify;
- 传输与来源防护:支持 HTTPS 加密传输、请求来源白名单、脚本来源白名单与脚本完整性校验(SRI),防范中间人攻击与篡改注入风险;
- 组件加密分发:前端组件(captcha.js / captcha.css)以密文形式存储于服务端,由内置解密端点实时输出,脚本本体经混淆加固,显著提高逆向分析与篡改破解难度;
- 服务端行为历史风控:挑战难度与信誉评分主要由服务端行为历史(历史通过率、失败率、异常统计)决定,客户端上报的环境信号仅作辅助参考,伪造客户端参数无法主导难度判定;
- 多维度频率控制:对各类接口实施多维度访问频率控制,有效抵御批量爆破与资源耗尽式攻击;
- 错误信息脱敏:服务端内部异常对客户端统一返回脱敏提示,不泄露内部实现细节;
- 跨站接入可靠:V2 起挑战与浏览器会话解耦,Safari / Firefox / Chrome 拦截第三方 Cookie 的场景下验证不再失效。
错误码表#
接口返回统一为 {"code":错误码,"msg":"原因","data":{...}},HTTP 状态码与错误码前三位一致。错误码分两个体系:API 层(5 位,凭证/计费/限流等)与引擎校验层(3 位,action=check 的答案/行为/挑战状态判定)。
API 层错误码(get / check / tokenVerify 均可能返回)
| 错误码 | HTTP | 原因 | 处理建议 |
|---|---|---|---|
| 40001 | 400 | 参数错误:缺少必要参数或格式不正确 | 对照本文档检查 action/type/appId 等参数是否齐全 |
| 40002 | 400 | 验证模式无效 | type 仅支持 click / slide / rotate |
| 40101 | 401 | AppID 无效或不存在 | 到用户中心核对 AppID,注意复制时不要带空格 |
| 40102 | 401 | AppSecret 校验失败 | 核对 AppSecret;怀疑泄露请在用户中心重置 |
| 40103 | 401 | token 无效、已过期或已被使用 | token 300 秒有效且一次性,引导用户重新验证 |
| 40104 | 401 | 请先登录后再体验在线演示 | 首页在线演示仅向登录用户开放,登录或注册后重试 |
| 40201 | 402 | 接口调用额度不足 | 账户余额为 0,请充值后再调用 |
| 40301 | 403 | 请求来源非法(未在 Origin 白名单内) | 确认请求 Origin 已加入 YZ_ALLOWED_ORIGINS 白名单 |
| 41001 | 410 | 验证挑战已过期 | 挑战有效期 180 秒,刷新验证码重新验证 |
| 42901 | 429 | 请求过于频繁,触发限流 | 降低请求频率,采用指数退避重试 |
| 50001 | 500 | 验证服务内部错误 | 稍后重试,持续失败请联系技术支持 |
| 50002 | 500 | 账户数据异常 | 联系客服核查账户状态 |
| 50003 | 500 | 数据库服务异常 | 稍后重试,持续失败请联系技术支持 |
引擎校验错误码(action=check 返回)
| 错误码 | HTTP | 典型消息 | 原因与处理建议 |
|---|---|---|---|
| 200 | 200 | 验证成功 | 校验通过,data.token 为一次性安全凭据 |
| 400 | 400 | 验证数据格式错误 / 请依次点击 3 个指定文字 | 请求字段缺失或格式错误(points/x/angle/meta),挑战随即作废,重新获取 |
| 401 | 401 | 验证失败,请重新尝试 | 答案错误(点选位置/顺序、滑块位置、旋转角度或翻转状态不符),挑战作废需重新获取 |
| 403 | 403 | 检测到异常操作行为 | 行为模型判定为机器操作;正常用户放慢操作重试,勿使用自动化工具 |
| 405 | 405 | 请求方式错误 | check 必须 POST 请求 |
| 410 | 410 | 验证已失效,请刷新后重试 / 验证已过期,请重新验证 | 挑战不存在、已被消费或超过 180 秒有效期;旧版组件跨站 Cookie 被拦截也会触发,请升级到最新 captcha.js(challengeId 机制) |
| 429 | 429 | 验证请求过于频繁 / 验证失败次数过多 | 触发限流或单挑战尝试超限,降低频率后重新获取挑战 |
| 500 | 500 | 服务暂不可用,请稍后重试 | 服务端内部故障(脱敏输出),联系技术支持排查 error_log |
更多帮助#
接入过程中遇到问题,请先查阅常见问题,其中覆盖了图片加载失败、token 校验失败、限流、跨域等高频问题的排查步骤与示例代码。已注册用户可直接到用户中心获取已填入 AppID 的快速接入代码。