- 网络安全
- 应用安全
- 后端
【免费下载链接】cap
Free, open-source and self-hosted CAPTCHA alternative to reCAPTCHA. Privacy-first and powered by proof-of-work and instrumentation challenges.
Cap 是一个免费、开源、可自托管的 CAPTCHA 替代方案,用**不可见的 proof-of-work(工作量证明)**取代图片拼图:用户只需要点一下复选框,浏览器在后台静默完成计算,全程无 Cookie、无追踪、无第三方调用。本文以官方 Quickstart 为骨架,带你完成服务器部署(Docker)→ 前端接入(Web Component)→ 服务端验签(siteverify)→ 端到端验证的完整闭环,并深入源码说明每个环节背后的真实实现。
一、先理解 Cap 的两段式架构
Cap 只有两个组成部分:
- Widget(前端组件):运行挑战、展示复选框,负责在用户浏览器中“干活”。它是一个原生 Web Component(
<cap-widget>),核心实现在 widget/src/src/cap.js。 - Server(后端服务):签发挑战、验证解答。推荐部署方式是Cap Standalone——单个容器同时提供小型 REST API 和用于管理站点密钥的 Web 仪表盘,支持多个 site key,并且兼容 reCAPTCHA 的 siteverify API(详见 Cap Standalone)。
两者的交互很简单:用户点击复选框后,Widget 向后端POST /challenge申请挑战并本地求解,随后向后端POST /redeem兑换得到一个一次性 token,最终 token 随表单提交到你的业务服务,由你的服务端调用/siteverify完成验签。你可以从 standalone/src/cap.js 的源码中看到/:siteKey/challenge与/:siteKey/redeem两个路由的完整实现。
::: tip 已经在用 reCAPTCHA? Cap 的/siteverify与 reCAPTCHA 的 API 兼容。把现有校验代码的 URL 换掉即可同时运行两套系统,随时切换,无需重写代码、也没有一次性“大爆炸”式切换的风险。特性对比见 feature comparison。 :::
二、准备工作
- Docker(跑服务器最快的方式)
- 一个能被用户浏览器访问到的部署位置(域名或公网 IP,不能是
localhost) - 几分钟时间
三、第一步:跑起服务器
3.1 编写 docker-compose.yml
创建docker-compose.yml(仓库中已有同款示例,可直接对照 standalone/docker-compose.yml):
services: cap: image: tiago2/cap:latest container_name: cap ports: - "3000:3000" environment: ADMIN_KEY: your_secret_password REDIS_URL: redis://valkey:6379 depends_on: valkey: condition: service_healthy restart: unless-stopped valkey: image: valkey/valkey:9-alpine container_name: cap-valkey volumes: - valkey-data:/data command: valkey-server --save 60 1 --loglevel warning --maxmemory-policy noeviction healthcheck: test: ["CMD", "valkey-cli", "ping"] interval: 5s timeout: 3s retries: 5 restart: unless-stopped volumes: valkey-data:3.2 启动并创建站点密钥
docker compose up -d打开http://localhost:3000(或服务器 IP / 域名:3000),用ADMIN_KEY登录,然后创建一个 site key。你会拿到一对凭证:
- site key:公开的站点密钥,用于 Widget 端
- secret key:机密的验证密钥,用于服务端验签
两者都要妥善保存,下一步要用。
::: tip 提示
ADMIN_KEY是仪表盘登录密码,建议至少 32 个字符。- 如果 3000 端口被占用,修改
3000:3000的左侧映射。 - 如果仪表盘访问不到,在
cap服务下增加network_mode: "host"。 :::
从源码看,密钥本身是加密生成的:site key 是 5 字节随机数的 hex 串,secret key 是sk-前缀加 32 字节随机 base64,且 secret 在入库前会经过hashSecret哈希处理,只在创建时明文返回一次(见 standalone/src/server.js 中POST /server/keys的实现);之后也可以随时通过/server/keys/:siteKey/rotate-secret轮换 secret key。
四、第二步:接入前端 Widget
Widget 是一个单文件 Web Component。以 CDN 方式引入(生产环境建议锁定版本号,不锁定就用latest):
<script src="https://cdn.jsdelivr.net/npm/cap-widget@<version>"></script>::: tip 锁定版本请参考官方 release 页面;高安全场景下可以把该 JS 文件自托管,而不是从 CDN 加载——Cap Standalone 甚至内置了资产服务器,可参考 Options - Asset server。 :::
4.1 最简单的方式:放进表单即可
如果<cap-widget>位于<form>内部,Cap 会自动注入一个隐藏的cap-token字段,随表单其余数据一起提交,完全不需要写 JavaScript:
<form action="/submit" method="POST"> <!-- your fields --> <cap-widget>const widget = document.querySelector("cap-widget"); widget.addEventListener("solve", (e) => { const token = e.detail.token; // send token to your server, enable the submit button, etc. });Widget 共派发 4 种事件:solve(成功,detail.token)、progress(进度,detail.progress)、error(出错,detail.message)、reset(重置),完整事件表与 React/Vue/Svelte/SolidJS/Astro/Preact/Qwik 等框架代码片段都在 widget 页面 中。
另外你还可以:
- 无界面化:通过 programmatic 模式 在后台直接
cap.solve()拿到 token,适合保护发帖等后台动作; - 悬浮模式:使用 floating 模式,组件悬浮在页面角落;
- 自定义样式:通过
--cap-background、--cap-border-radius、--cap-widget-width等 CSS 变量覆盖外观(见 Widget - Styling); - 多语言:通过
data-cap-i18n-*属性覆盖所有界面文案,默认英文(见 Widget - i18n)。
五、第三步:服务端验证 token
在信任任何表单提交之前,服务端必须校验 token。向实例的/siteverify端点发送POST:
::: code-group
curl "https://<your-instance>/<site-key>/siteverify" \ -X POST \ -H "Content-Type: application/json" \ -d '{ "secret": "<key_secret>", "response": "<captcha_token>" }'const { success } = await ( await fetch("https://<your-instance>/<site-key>/siteverify", { method: "POST", headers: { "Content-Type": "application/json" }, body: JSON.stringify({ secret: "<key_secret>", response: "<captcha_token>" }), }) ).json(); if (!success) throw new Error("invalid cap token");import requests success = requests.post( "https://<your-instance>/<site-key>/siteverify", json={"secret": "<key_secret>", "response": "<captcha_token>"}, ).json().get("success")<?php $data = json_decode(file_get_contents("https://<your-instance>/<site-key>/siteverify", false, stream_context_create([ "http" => [ "method" => "POST", "header" => "Content-Type: application/json", "content" => json_encode(["secret"=>"<key_secret>","response"=>"<captcha_token>"]) ] ]) ), true); var_dump($data['success'] ?? false);:::
两个参数务必区分清楚:
<key_secret>是仪表盘里的secret key,不是仪表盘登录用的ADMIN_KEY。把两者搞混是最常见的配置错误。<captcha_token>是 Widget 生成的 token(cap-token表单字段或e.detail.token)。
验证通过返回:
{ "success": true }从源码看,standalone/src/siteverify.js 中的校验过程包含四层检查:响应格式(sitekey:redeemId:redeemSecret三段结构)、site key 与 secret 的哈希比对(verifySecret)、token 是否存在(RedisGETDEL原子取删)、token 是否过期(时间戳比对)。token 是单次使用的——GETDEL一旦取走即删除,所以每个 token 只能验一次,之后请执行你自己的业务逻辑(创建账号、发送消息等)。
六、第四步:端到端确认
快速做一次完整检查:
- 加载你的页面。复选框应自动打勾,
solve处理器(或表单字段)应产生 token。 - 把 token 发给
/siteverify,应返回{ "success": true }。 - 再发同一个 token 一次,这次应该失败——这证实了单次使用机制在正常工作。
如果验证总是失败,检查你是否用了 secret key(而不是 admin key),以及<your-instance>是否与 Widget 指向的 URL 完全一致(一致才不会被 site key 前缀校验拦截,见 standalone/src/siteverify.js 中response.startsWith(sitekeyraw)的检查)。
至此集成完成:用户在浏览器里解挑战,你的服务端验证 token,每一个字节的数据都留在你自己的基础设施里。
七、超越 Quickstart:把部署调优到生产级
Quickstart 是 5 分钟的落地路径,但生产环境还需要理解 Standalone 的几个关键配置面(详见 Options 指南)。
7.1 挑战与限流
Standalone 对挑战类端点按客户端 IP 做固定窗口限流,默认 30 次 / 5 秒,超出返回429并带X-RateLimit-Remaining: 0头。全局值可在仪表盘 Settings 修改(等价于PUT /settings/ratelimit),也可在单个 site key 的 Configuration 页按 key 覆盖。/siteverify是服务端到服务端接口,默认不限流。
反向代理场景下必须正确转发客户端 IP:默认按X-Forwarded-For、X-Real-IP、CF-Connecting-IP(依序)识别,回退到 socket 地址。nginx 示例:
location / { proxy_pass http://localhost:3000; proxy_set_header X-Forwarded-For $remote_addr; }注意:X-Forwarded-For是原样信任的,所以服务器绝不能直接暴露在公网上,否则客户端可以伪造该头绕过限流(源码依据见 standalone/src/cap.js 中getClientIp的取头逻辑与 standalone/src/ratelimit.js 的固定窗口实现)。
7.2 挑战协议:HashWX 是默认
Standalone 默认使用HashWX——一种 GPU 抗性工作量证明:每次挑战都从种子现场生成一个新的单向函数(由整数运算与分支构成),GPU 无法比 CPU 快多少(实测 GPU 优势仅约 2 倍,而 SHA-256 是约 150 倍)。服务器端成本约为每挑战 54 µs(mint 14 µs + verify 40 µs,M3 单核中位数),详细原理与测量数据见 HashWX proof of work。
每个 site key 可在 Configuration 页选择协议:
- HashWX(默认):无需生成密钥对,开箱即用;
- SHA-256 PoW:有纯 JS 回退,适合不支持 WebAssembly 的客户端;
- RSW 时间锁谜题:已弃用,仅存量部署可选——GPU 能约以 170 倍速度并行处理,失去设计初衷。
关键参数与范围(源码校验于 standalone/src/cap.js 与 standalone/src/server.js):
| 参数 | 默认值 | 取值范围 | 说明 |
|---|---|---|---|
difficulty | 4 | 1–8 | SHA-256 PoW 难度 |
challengeCount | 80 | 1–500 | SHA-256 挑战数量 |
instrumentation | false | true/false | 是否启用 instrument 挑战(仪表盘新建 key 时默认开启) |
obfuscationLevel | 3 | 1–10 | instrument 脚本混淆级别,级别越高生成吞吐越低 |
hashwxDifficulty | 1_000_000 | 50_000–5_000_000 | HashWX 期望哈希数,默认拆分为 4 个子挑战 |
rswT | 75_000 | 10_000–300_000 | RSW 顺序平方次数 |
7.3 健康检查与优雅停机
Standalone 暴露两个免鉴权端点:
GET /health:Redis 2 秒内应答PING返回200 {"status":"ok"},否则503 {"status":"unavailable"},用于就绪探针;GET /health/live:只要进程存活即返回 200,用于存活探针,避免 Redis 故障期间编排器反复重启。
同秒内的检查共享一次PING,轮询不增加 Redis 负载。Kubernetes 探针示例:
readinessProbe: httpGet: path: /health port: 3000 livenessProbe: httpGet: path: /health/live port: 3000收到SIGTERM/SIGINT时,Cap 停止接收新连接、等存量请求完成、关闭 Redis 连接并以码 0 退出;8 秒后仍在运行的请求则以码 1 退出,适配 Docker 默认 10 秒停止超时。
7.4 合规性设计
Cap 自托管、无 Cookie、无追踪、无第三方调用,用户数据从不离开你的基础设施,设计上围绕 GDPR、CCPA、HIPAA、LGPD 等隐私法规展开;proof-of-work 复选框也规避了 WCAG 2.2 对图片/音频谜题的无障碍障碍(详见 Compliance)。
八、下一步
表单保护已经就位,接下来可以:
- 用 框架代码片段 把 Cap 接入你的技术栈
- 定制 Widget 外观与行为
- 调优 instrumentation 与 CORS、限流等配置
- 对比 reCAPTCHA、Turnstile、hCaptcha 等方案
- 若仍在选型,阅读 2026 最佳 CAPTCHA 替代方案指南
如果想在仓库里继续深入:完整的挑战签发/兑换逻辑见 standalone/src/cap.js,验签逻辑见 standalone/src/siteverify.js,site key 管理 API 见 standalone/src/server.js,Widget 端实现见 widget/src/src/cap.js,对应测试可参考 standalone/test/hashwx-routes.test.js 与 standalone/test/cap-routes.test.js。
- 网络安全
- 应用安全
- 后端
【免费下载链接】cap
Free, open-source and self-hosted CAPTCHA alternative to reCAPTCHA. Privacy-first and powered by proof-of-work and instrumentation challenges.
相关推荐
Cap 快速接入指南:5 分钟自托管部署 Proof-of-Work CAPTCHA 并完成 Token 验证
Cap 快速接入指南:5 分钟自托管部署 Proof of Work CAPTCHA 并完成 Token 验证 Cap 是一个免费、开源、可自托管的 CAPTC
网络安全应用安全后端Cap 快速上手指南:五分钟自托管 reCAPTCHA 替代方案,用 proof-of-work 打造无感验证码
Cap 快速上手指南:五分钟自托管 reCAPTCHA 替代方案,用 proof of work 打造无感验证码 Cap 是一个免费、开源、可完全自托管的 CA
网络安全应用安全后端5分钟完成Google-github-actions/auth配置:Workload Identity Federation快速上手指南
5分钟完成Google github actions/auth配置:Workload Identity Federation快速上手指南 Google gith
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考