首页 验证体验 登录演示 注册演示 接入文档 价格套餐

接入文档

将枢爻验证码集成到你的网站,只需 3 步,5 分钟搞定。

接入流程

整个接入过程分为前端后端两部分,前端负责展示验证码,后端负责校验结果:

1
前端引入 SDK
在你的页面引入 CSS + JS
2
用户完成验证
SDK 弹出验证码,用户操作通过后获得 token
3
前端提交 token
把 token 随表单一起发给你的后端
4
后端校验 token
你的后端调用验证码服务确认 token 有效

⚠️ 重要:token 必须在你的后端校验,不能只在前端判断。前端回调只代表用户操作完成,不代表安全可信。

3 步快速接入

第 1 步 前端:引入 SDK 并触发验证

在你的 HTML 页面中加入以下代码。YOUR_SERVER 替换为验证码服务的地址,YOUR_APP_ID 替换为在管理后台创建的应用 ID。

HTML
<!-- 1. 引入验证码样式 -->
<link rel="stylesheet" href="https://YOUR_SERVER/sdk/shuyao-captcha.css">

<!-- 2. 你的提交按钮 -->
<button id="submitBtn">提交</button>

<!-- 3. 初始化验证码 -->
<script type="module">
  import { ShuyaoCaptcha } from 'https://YOUR_SERVER/sdk/shuyao-captcha.js';

  const captcha = ShuyaoCaptcha.init({
    serverUrl: 'https://YOUR_SERVER',  // 验证码服务地址
    appId:     'YOUR_APP_ID',          // 应用 ID
    onSuccess(token) {
      // 用户验证通过!把 token 发给你的后端
      fetch('/api/login', {
        method: 'POST',
        headers: { 'Content-Type': 'application/json' },
        body: JSON.stringify({ captchaToken: token })
      });
    }
  });

  // 点击按钮弹出验证码
  document.getElementById('submitBtn').addEventListener('click', () => {
    captcha.show();
  });
</script>

第 2 步 后端:校验 token

你的后端收到前端提交的 token 后,调用验证码服务的 /api/v1/captcha/validate 接口确认是否有效:

你的后端 → 验证码服务
// 请求
POST https://YOUR_SERVER/api/v1/captcha/validate
Content-Type: application/json

{ "token": "用户提交的 token 值" }

// 响应
{ "valid": true }   ← true 表示验证通过,可以继续业务
{ "valid": false }  ← false 表示 token 无效或已过期

💡 token 是一次性的,校验后立即失效。有效期 300 秒。

第 3 步 根据校验结果处理业务

伪代码
function handleLogin(request) {
  // 1. 拿到前端提交的 token
  token = request.body.captchaToken

  // 2. 调用验证码服务校验
  result = httpPost("https://YOUR_SERVER/api/v1/captcha/validate", { token: token })

  // 3. 判断是否通过
  if (!result.valid) {
    return error("验证码校验失败")
  }

  // 4. 验证通过,继续你的正常业务逻辑
  doLogin(request.body.username, request.body.password)
}

就这么简单!下面是详细的 API 参考和各语言的示例代码。

POST /api/v1/captcha/init — 初始化会话

POST /api/v1/captcha/init

SDK 内部自动调用。生成会话 ID、ECDH 密钥对、PoW 挑战参数。

请求体

字段类型必填说明
appIdString你的应用 ID(在管理后台创建)
clientInfoObject客户端环境信息,由 SDK 自动采集
clientInfo.fingerprintString设备指纹
clientInfo.webdriverBoolean是否检测到 WebDriver
clientInfo.headlessBoolean是否为无头浏览器

响应体

JSON
{
  "sessionId":       "550e8400e29b41d4a716446655440000",
  "serverPublicKey":  "MFkwEwYHKoZIzj0C...",      // ECDH 公钥
  "powDifficulty":    16,                           // PoW 难度
  "powPrefix":        "550e8400...:a1b2c3d4...",   // PoW 前缀
  "timestamp":        1682406316000                  // 服务器时间戳
}

POST /api/v1/captcha/challenge — 获取验证挑战

POST /api/v1/captcha/challenge

SDK 内部自动调用。根据风险评估生成验证挑战(图形推理或轨迹追踪)。

请求体

字段类型必填说明
sessionIdString从 init 接口获得的会话 ID
clientPublicKeyString客户端 ECDH 公钥(启用加密时需要)
environmentDataObject环境检测数据
preferredTypeString指定挑战类型:TRANSFORMATION 或 TRAJECTORY

响应体

JSON
{
  "challengeId": "abc123def456...",
  "type":        "TRANSFORMATION",    // 或 TRAJECTORY
  "renderData":  { ... },               // 渲染数据(可能加密)
  "encrypted":   false                   // 是否已加密
}

POST /api/v1/captcha/verify — 提交验证

POST /api/v1/captcha/verify

SDK 内部自动调用。提交用户答案、行为数据,进行防重放、PoW、答案、行为四重验证。

请求体

字段类型必填说明
sessionIdString会话 ID
challengeIdString挑战 ID
answerString用户答案
behaviorDataObject行为采集数据(鼠标事件、耗时等)
powNonceStringPoW 计算结果
timestampLong客户端时间戳
nonceString请求唯一标识(防重放)

响应体

JSON - 成功
{
  "success": true,
  "token":   "NTUwZTg0MDAtZTI5Yi00MWQ0...",  // 验证 Token
  "message": "验证通过"
}
JSON - 失败
{
  "success": false,
  "token":   null,
  "message": "验证失败,请重试"
}

POST /api/v1/captcha/validate — 校验 Token

POST /api/v1/captcha/validate

这是你需要在自己后端调用的唯一接口。其他接口都由 SDK 自动处理。

🔒 此接口应由你的服务器调用,不要在前端 JavaScript 中直接调用。Token 一次性使用,验证后立即失效。

请求体

JSON
{
  "token": "用户验证通过后获得的 token 字符串"
}

响应体

字段类型说明
validBooleantrue = 验证通过,可信赖;false = 无效或已过期
JSON
{ "valid": true }

引入 SDK

SDK 由一个 CSS 文件和一个 JS 模块组成,无任何第三方依赖。

HTML
<!-- 引入样式 -->
<link rel="stylesheet" href="https://YOUR_SERVER/sdk/shuyao-captcha.css">

<!-- 引入 JS(ES Module) -->
<script type="module">
  import { ShuyaoCaptcha } from 'https://YOUR_SERVER/sdk/shuyao-captcha.js';
</script>

💡 把 YOUR_SERVER 替换为你部署验证码服务的域名或 IP,例如 https://captcha.example.com。如果通过 Nginx 反向代理访问,直接用你的网站域名即可。

配置参数

参数类型必填默认值说明
serverUrlString验证码后端 API 地址(如 https://captcha.example.com
appIdString应用 ID(在管理后台「应用管理」中创建获取)
themeString'light'主题样式:'light'(浅色)或 'dark'(深色)
onSuccessFunction验证成功回调,参数为 token 字符串
onFailFunction验证失败回调,参数为失败原因字符串
onCloseFunction用户关闭验证码弹窗时触发

方法与回调

方法

方法说明
ShuyaoCaptcha.init(config)初始化,传入配置,返回实例
实例.show()弹出验证码窗口,开始验证
实例.destroy()销毁实例,移除所有 DOM 和事件

回调事件

回调触发时机参数你需要做什么
onSuccess用户验证通过token(String)把 token 发给你的后端校验
onFail验证失败message(String)提示用户重试
onClose用户关闭弹窗可选处理

完整前端示例

一个登录页面的完整接入示例:

HTML
<!DOCTYPE html>
<html>
<head>
  <link rel="stylesheet" href="https://YOUR_SERVER/sdk/shuyao-captcha.css">
</head>
<body>
  <form id="loginForm">
    <input name="username" placeholder="用户名">
    <input name="password" type="password" placeholder="密码">
    <button type="button" id="loginBtn">登录</button>
  </form>

  <script type="module">
    import { ShuyaoCaptcha } from 'https://YOUR_SERVER/sdk/shuyao-captcha.js';

    const captcha = ShuyaoCaptcha.init({
      serverUrl: 'https://YOUR_SERVER',
      appId: 'YOUR_APP_ID',
      onSuccess(token) {
        const form = document.getElementById('loginForm');
        fetch('/api/login', {
          method: 'POST',
          headers: { 'Content-Type': 'application/json' },
          body: JSON.stringify({
            username: form.username.value,
            password: form.password.value,
            captchaToken: token
          })
        }).then(r => r.json())
          .then(data => {
            if (data.success) alert('登录成功');
            else alert(data.message || '登录失败');
          });
      },
      onFail(msg) { alert('验证失败: ' + msg); }
    });

    document.getElementById('loginBtn').addEventListener('click', () => {
      captcha.show();
    });
  </script>
</body>
</html>

Java / Spring Boot 后端校验

Java
@PostMapping("/api/login")
public ResponseEntity<?> login(@RequestBody LoginRequest req) {
    // 1. 向验证码服务校验 token
    RestTemplate rest = new RestTemplate();
    Map<String, String> body = Map.of("token", req.getCaptchaToken());
    Map result = rest.postForObject(
        "https://YOUR_SERVER/api/v1/captcha/validate", body, Map.class);

    if (!(Boolean) result.get("valid")) {
        return ResponseEntity.badRequest().body("验证码校验失败");
    }

    // 2. 验证通过,处理登录逻辑...
    return ResponseEntity.ok("登录成功");
}

Node.js / Express 后端校验

JavaScript
app.post('/api/login', async (req, res) => {
  // 1. 向验证码服务校验 token
  const resp = await fetch('https://YOUR_SERVER/api/v1/captcha/validate', {
    method: 'POST',
    headers: { 'Content-Type': 'application/json' },
    body: JSON.stringify({ token: req.body.captchaToken })
  });
  const { valid } = await resp.json();

  if (!valid) {
    return res.status(400).json({ error: '验证码校验失败' });
  }

  // 2. 验证通过,处理登录逻辑...
  res.json({ success: true });
});

Python / Flask 后端校验

Python
@app.route('/api/login', methods=['POST'])
def login():
    token = request.json.get('captchaToken')

    # 1. 向验证码服务校验 token
    resp = requests.post(
        'https://YOUR_SERVER/api/v1/captcha/validate',
        json={'token': token}
    )

    if not resp.json().get('valid'):
        return jsonify(error='验证码校验失败'), 400

    # 2. 验证通过,处理登录逻辑...
    return jsonify(success=True)

PHP 后端校验

PHP
// 1. 向验证码服务校验 token
$token = $_POST['captchaToken'];
$ch = curl_init('https://YOUR_SERVER/api/v1/captcha/validate');
curl_setopt($ch, CURLOPT_POST, true);
curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode(['token' => $token]));
curl_setopt($ch, CURLOPT_HTTPHEADER, ['Content-Type: application/json']);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
$result = json_decode(curl_exec($ch), true);
curl_close($ch);

if (!$result['valid']) {
    die('验证码校验失败');
}

// 2. 验证通过,处理登录逻辑...

GET /api/v1/admin/stats — 统计数据

GET /api/v1/admin/stats

获取系统运行统计:验证总量、通过率、每日趋势、类型分布、风险分布。

JSON 响应
{
  "totalVerifyCount":  10000,       // 总验证次数
  "passCount":         8500,        // 通过次数
  "blockCount":        1500,        // 拦截次数
  "passRate":          85.0,        // 通过率 (%)
  "todayVerifyCount":  1200,        // 今日验证
  "todayPassCount":    1020,        // 今日通过
  "todayBlockCount":   180,         // 今日拦截
  "dailyStats": {                     // 每日验证数(近7天)
    "2026-04-15": 1100,
    "2026-04-16": 1200, ...
  },
  "typeStats": {                      // 挑战类型分布
    "TRANSFORMATION": 6000,
    "TRAJECTORY": 4000
  },
  "riskStats": {                      // 风险等级分布
    "LOW": 6500, "MEDIUM": 2000,
    "HIGH": 1000, "CRITICAL": 500
  }
}

GET /api/v1/admin/logs — 验证日志

GET /api/v1/admin/logs

分页查询验证日志,支持按状态和 IP 过滤。

查询参数

参数类型默认值说明
pageInteger1页码
sizeInteger20每页条数
statusString过滤状态:passed(通过)/ blocked(拦截)
ipString按 IP 地址模糊搜索

响应

JSON
{
  "logs": [{
    "id": 1,
    "timestamp": 1682406316000,
    "clientIp": "192.168.1.100",
    "challengeType": "TRANSFORMATION",
    "passed": true,
    "riskScore": 25,
    "duration": 3500,
    "sessionId": "550e8400..."
  }],
  "total": 10000,
  "page": 1,
  "size": 20
}

应用管理 API

GET /api/v1/admin/appkeys — 获取应用列表

JSON 响应
[{
  "appId":        "shuyao_abc123def456",
  "appKey":       "sk_live_xyz789uvw...",
  "appName":      "我的网站",
  "status":       "ENABLED",
  "createdAt":    1682406316000,
  "monthlyQuota": 100000,
  "usedCount":    12345,
  "domains":      ["localhost", "*.example.com"]
}]

POST /api/v1/admin/appkeys — 创建新应用

JSON 请求
{
  "appName": "我的网站",
  "domains": ["localhost", "*.mysite.com"]  // 可选,默认 ["localhost"]
}

POST /api/v1/admin/appkeys/{appId}/reset — 重置密钥

重新生成 appKey,旧密钥立即失效。响应返回新的 appKey。

POST /api/v1/admin/appkeys/{appId}/toggle — 启用/禁用

JSON 请求
{ "enabled": true }  // true=启用, false=禁用

PUT /api/v1/admin/appkeys/{appId}/domains — 更新授权域名

JSON 请求
{ "domains": ["localhost", "*.newdomain.com"] }

DELETE /api/v1/admin/appkeys/{appId} — 删除应用

永久删除应用,操作不可撤销。

风控配置 API

GET /api/v1/admin/riskconfig — 获取配置

JSON 响应
{
  "ipRateLimit":          true,   // IP 频率限制
  "fingerprintDetect":    true,   // 设备指纹检测
  "headlessDetect":       true,   // 无头浏览器检测
  "webdriverDetect":      true,   // WebDriver 检测
  "powEnabled":           true,   // PoW 工作量证明
  "adaptiveDifficulty":   true,   // 自适应难度
  "encryptTransport":     true,   // ECDH+AES 加密传输
  "antiReplay":           true,   // 防重放保护
  "maxRequestsPerMinute": 30,     // 每分钟最大请求数
  "powDefaultDifficulty": 16,     // PoW 默认难度
  "powHighDifficulty":    20      // PoW 高风险难度
}

PUT /api/v1/admin/riskconfig — 更新配置

请求体结构与 GET 响应相同,修改后实时生效。

DELETE /api/v1/admin/cache/clear — 清除缓存

DELETE /api/v1/admin/cache/clear

清除 Redis 中所有 shuyao:* 前缀的缓存数据。清除后会话和挑战需重新生成。

JSON 响应
{ "success": true, "message": "Redis 缓存已清除" }

加密通信

系统使用 ECDH(椭圆曲线 Diffie-Hellman) 协商共享密钥,通过 AES-GCM 加密验证数据传输,防止中间人攻击。整个过程由 SDK 自动完成,无需额外配置。

参数
椭圆曲线secp256r1 (P-256)
对称加密AES-GCM(128 位 Tag)
IV 长度12 字节(随机)
共享密钥导出ECDH 原始密钥 → SHA-256 → 32 字节

风控策略

系统根据 IP 频率、客户端环境、设备指纹三个维度综合评估风险,自动选择挑战类型和难度:

风险等级评分范围挑战类型PoW 难度
低风险0 - 29爻变推演(简单)16 位
中风险30 - 59爻变推演(中等)16 位
高风险60 - 84轨迹密钥(复杂)20 位
极高风险85+复合验证20 位