Guard 接入指南

Sad Guard 是由伤心的云运营的人机验证服务。本文档说明如何将它接入你的网站或应用。

概览

一次完整的验证流程分三步:

浏览器(你的页面)                Guard 服务器                 你的后端
    │                                │                         │
    │── POST /{siteKey}/handshake ──▶│                         │
    │◀── 挑战数据 + ticket ──────────│                         │
    │                                │                         │
    │  [用户在页面上完成验证]          │                         │
    │── POST /{siteKey}/confirm ────▶│                         │
    │◀── 一次性 pass token ──────────│                         │
    │                                │                         │
    │── 把 pass token 随表单 ───────│────────────────────────▶│
    │                                │                         │── POST /siteverify ──▶│
    │                                │                         │◀── {success:true} ────│
    │                                │                         │
    │◀──────────── 业务响应(登录/注册/发送验证码等)──────────│

Guard 不参与你的业务逻辑——它只负责发放和校验一次性 pass token。


第一步:获取密钥

  1. 登录 Guard 管理面板(默认地址 /admin)。
  2. 进入 Site Keys,点击创建。
  3. 你会得到两个值: - Site Key(公开):前端 widget 使用。 - Secret Key(保密):后端调用 /siteverify 时使用。不要放到前端代码里。

第二步:前端接入

在你的 HTML 页面里加入两行代码:

<!-- 1. 引入组件脚本(一次) -->
<script src="https://guard.sad.kim/guard.js" defer></script>

<!-- 2. 放置验证组件(在表单里) -->
<guard-widget
  site-key="YOUR_SITE_KEY"
  api="https://guard.sad.kim">
</guard-widget>

验证完成后的事件监听

widget 在验证通过时会派发 solved 事件,携带一次性 pass token:

<script>
  const widget = document.querySelector('guard-widget');

  widget.addEventListener('solved', (e) => {
    const passToken = e.detail.token;
    // 把 passToken 随表单一起提交给你的后端
    document.getElementById('guardToken').value = passToken;
  });

  widget.addEventListener('error', (e) => {
    console.error('验证失败', e.detail.error);
  });
</script>

隐藏表单字段

widget 内部会自动渲染一个 <input type="hidden" name="guard-token">。如果你的表单名不同,用 field-name 属性覆盖:

<guard-widget
  site-key="YOUR_SITE_KEY"
  api="https://guard.sad.kim"
  field-name="captcha_token">
</guard-widget>

Widget 属性一览

属性 必填 默认值 说明
site-key 管理面板里的 Site Key
api Guard 服务器地址(不带尾部 /
field-name guard-token 隐藏 input 的 name
mode 服务端配置 强制使用某种验证模式(pow / pow_slider / pow_click

编程式控制

widget 暴露两个方法,可在 JS 中直接调用:

const w = document.querySelector('guard-widget');

w.solve();  // 主动发起验证(需先完成上一次的 reset)
w.reset();  // 重置状态,可再次验证

第三步:后端验证

用户提交表单后,你的后端会拿到 pass token。必须调 Guard 的 /siteverify 接口核销——否则攻击者可以伪造任意 token 绕过验证。

请求

POST https://guard.sad.kim/siteverify
Content-Type: application/json

{
  "secret": "YOUR_SECRET_KEY",
  "response": "<用户提交的 pass token>"
}

响应

// 成功
{ "success": true }

// 失败
{ "success": false, "error": "invalid_or_expired_token" }

关键约束

Python 示例

import requests

def verify_captcha(pass_token: str) -> bool:
    resp = requests.post(
        "https://guard.sad.kim/siteverify",
        json={
            "secret": "YOUR_SECRET_KEY",
            "response": pass_token,
        },
        timeout=5,
    )
    data = resp.json()
    return data.get("success") is True

Node.js 示例

async function verifyCaptcha(passToken) {
  const resp = await fetch('https://guard.sad.kim/siteverify', {
    method: 'POST',
    headers: { 'Content-Type': 'application/json' },
    body: JSON.stringify({
      secret: 'YOUR_SECRET_KEY',
      response: passToken,
    }),
  });
  const data = await resp.json();
  return data.success === true;
}

验证模式

Guard 支持三种验证强度,可在管理面板为每个 Site Key 单独配置:

模式 用户体验 适用场景
pow 无交互,后台计算约 1-3 秒 低风险接口(搜索、浏览)
pow_slider 拖动滑块拼图 登录、注册
pow_click 按顺序点击图中文字 高价值操作(支付、改密)

所有模式底层都强制完成 PoW 计算,自动脚本即使绕过交互挑战仍需付出算力成本。


常见错误码

前端 widget 派发 error 事件

e.detail.error 含义
invalid_site_key Site Key 不存在
challenge_failed 服务端无法生成挑战
invalid_solution 答案错误或行为判定为机器人
expired ticket 过期(超过 10 分钟)
already_used ticket 重放

后端 /siteverify 返回的错误

error 含义
missing_fields secret 或 response 缺失
invalid_secret Secret Key 不存在或不匹配
invalid_or_expired_token token 已被核销或已超时
invalid_request JSON 格式错误

安全建议

  1. 永远在后端核销 token。前端只负责拿 token,业务决策由后端做。
  2. Secret Key 不要提交到代码仓库。用环境变量或密钥管理服务。
  3. 限制 CORS 来源。在管理面板为 Site Key 配置 CORS Origins,只允许你的域名,防止 token 被其他网站盗用。
  4. 高风险操作建议叠加 rate limit。Guard 自带 IP 限速,但业务层再加一道更稳妥。
  5. 定期轮换 Secret Key。管理面板里每个 Site Key 都有”Rotate Secret”按钮。

部署提示


最小可运行示例

保存为 demo.html,把 Site Key 和服务器地址换成你的:

<!DOCTYPE html>
<html lang="zh-CN">
<head>
  <meta charset="utf-8">
  <title>Guard 接入示例</title>
  <script src="https://guard.sad.kim/guard.js" defer></script>
</head>
<body>
  <h1>验证示例</h1>

  <guard-widget
    site-key="YOUR_SITE_KEY"
    api="https://guard.sad.kim">
  </guard-widget>

  <script>
    const widget = document.querySelector('guard-widget');

    widget.addEventListener('solved', (e) => {
      alert('验证通过!\npass token: ' + e.detail.token);
      // 真实场景:把 token 随表单提交到你的后端
    });

    widget.addEventListener('error', (e) => {
      alert('验证失败:' + e.detail.error);
    });
  </script>
</body>
</html>