ARTICLE DETAIL

建站实战干货

来自一线的建站与推广经验沉淀,每一条都经过真实交付验证。

Cap 快速上手:5 分钟自托管一套免 Google 的无感 CAPTCHA(Workload/Token 全流程实战)

2026/9/28 7:07:19 拓冰建站 浏览量
Cap 快速上手:5 分钟自托管一套免 Google 的无感 CAPTCHA(Workload/Token 全流程实战) 网络安全应用安全后端【免费下载链接】capFree, open-source and self-hosted CAPTCHA alternative to reCAPTCHA. Privacy-first and powered by proof-of-work and instrumentation challenges.项目地址https://gitcode.com/gh_mirrors/cap13/cap点击查看免费下载Cap 是一个免费、开源、可自托管的 CAPTCHA 替代方案用**不可见的 proof-of-work工作量证明**取代图片拼图用户只需要点一下复选框浏览器在后台静默完成计算全程无 Cookie、无追踪、无第三方调用。本文以官方 Quickstart 为骨架带你完成服务器部署Docker→ 前端接入Web Component→ 服务端验签siteverify→ 端到端验证的完整闭环并深入源码说明每个环节背后的真实实现。一、先理解 Cap 的两段式架构Cap 只有两个组成部分Widget前端组件运行挑战、展示复选框负责在用户浏览器中“干活”。它是一个原生 Web Componentcap-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.ymlservices: 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。四、第二步接入前端 WidgetWidget 是一个单文件 Web Component。以 CDN 方式引入生产环境建议锁定版本号不锁定就用latestscript srchttps://cdn.jsdelivr.net/npm/cap-widgetversion/script::: tip 锁定版本请参考官方 release 页面高安全场景下可以把该 JS 文件自托管而不是从 CDN 加载——Cap Standalone 甚至内置了资产服务器可参考 Options - Asset server。 :::4.1 最简单的方式放进表单即可如果cap-widget位于form内部Cap 会自动注入一个隐藏的cap-token字段随表单其余数据一起提交完全不需要写 JavaScriptform action/submit methodPOST !-- 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-groupcurl 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([secretkey_secret,responsecaptcha_token]) ] ]) ), true); var_dump($data[success] ?? false);:::两个参数务必区分清楚key_secret是仪表盘里的secret key不是仪表盘登录用的ADMIN_KEY。把两者搞混是最常见的配置错误。captcha_token是 Widget 生成的 tokencap-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 µsmint 14 µs verify 40 µsM3 单核中位数详细原理与测量数据见 HashWX proof of work。每个 site key 可在 Configuration 页选择协议HashWX默认无需生成密钥对开箱即用SHA-256 PoW有纯 JS 回退适合不支持 WebAssembly 的客户端RSW 时间锁谜题已弃用仅存量部署可选——GPU 能约以 170 倍速度并行处理失去设计初衷。关键参数与范围源码校验于 standalone/src/cap.js 与 standalone/src/server.js参数默认值取值范围说明difficulty41–8SHA-256 PoW 难度challengeCount801–500SHA-256 挑战数量instrumentationfalsetrue/false是否启用 instrument 挑战仪表盘新建 key 时默认开启obfuscationLevel31–10instrument 脚本混淆级别级别越高生成吞吐越低hashwxDifficulty1_000_00050_000–5_000_000HashWX 期望哈希数默认拆分为 4 个子挑战rswT75_00010_000–300_000RSW 顺序平方次数7.3 健康检查与优雅停机Standalone 暴露两个免鉴权端点GET /healthRedis 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.jssite key 管理 API 见 standalone/src/server.jsWidget 端实现见 widget/src/src/cap.js对应测试可参考 standalone/test/hashwx-routes.test.js 与 standalone/test/cap-routes.test.js。赞分享网络安全应用安全后端【免费下载链接】capFree, open-source and self-hosted CAPTCHA alternative to reCAPTCHA. Privacy-first and powered by proof-of-work and instrumentation challenges.项目地址https://gitcode.com/gh_mirrors/cap13/cap点击查看免费下载相关推荐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上一篇Apache Storm完整配置指南深入理解defaults.yaml与storm.yaml参数设置下一篇Python编程宝典30-seconds-of-python代码片段终极指南创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考