安装方式
命令行安装
在项目根目录执行以下命令,完成 Skill 安装。
npx bzskills add cloudflare/skills --skill turnstile-spin 在项目中端到端设置 Cloudflare Turnstile — 扫描代码库、通过 Cloudflare API 创建小部件、部署托管的 siteverify Worker、编写前端代码片段、验证并持久化该技能。当用户要求添加 Turnstile、设置验证码、保护表单免受机器人攻击或修复 Turnstile 集成时加载此项。镜像自 developers.cloudflare.com/turnstile/spin。
0
下载量
命令行安装
在项目根目录执行以下命令,完成 Skill 安装。
npx bzskills add cloudflare/skills --skill turnstile-spin name: turnstile-spin
description: 在项目中端到端设置 Cloudflare Turnstile — 扫描代码库、通过 Cloudflare API 创建小部件、部署托管的 siteverify Worker、编写前端代码片段、验证并持久化该技能。当用户要求添加 Turnstile、设置验证码、保护表单免受机器人攻击或修复 Turnstile 集成时加载此项。镜像自 developers.cloudflare.com/turnstile/spin。
references:
- vanilla-html
- nextjs-app
- nextjs-pages
- astro
- sveltekit
- hugo将提示“设置 Turnstile”转化为一个可用的端到端集成:一个 widget、一个已部署的托管 siteverify Worker、各个选定插入点的前端片段,以及在报告成功之前的真实验证环节。
你是代理。通过调用 scripts/ 下的脚本并根据它们的 JSON 输出进行分支来运行下面的向导。脚本包含确定性逻辑(API 调用、重试/错误处理);你的工作是编排、代码库读取、确认以及前端编辑。
规范说明位于 developers.cloudflare.com/turnstile/spin。如果文档页面与本文件不一致,请以文档页面为准。
当用户的提示中包含以下任何内容时加载:
不要为不相关的 Cloudflare 任务(Workers、Pages、R2 等)加载,除非同时也提到了 Turnstile。
用户粘贴了提示。你处于一个多步骤的对话中。检测你能检测到的内容,只有在必须时才询问,在每个不可逆步骤之前进行确认。每个编号的时刻对应一条代理消息。标记为 [等待用户] 的项需要用户响应。
npx wrangler --version。如果缺失,询问一次:“使用 npm install --save-dev wrangler(Node 项目)还是 npm install -g wrangler(其他方式)安装 wrangler?是否继续?” [等待用户] 如果完全无法安装(企业策略、npm 被阻止),则退回到通过 curl 调用 api.cloudflare.com/client/v4/ 来驱动步骤 4-5。scripts/auth-probe.sh。根据 status 分支:ok:继续到步骤 4。脚本已经选出账户(单账户 token,或与 $CLOUDFLARE_ACCOUNT_ID 匹配的账户)。missing_token、missing_scope 或 missing_workers_scope:请用户在 https://dash.cloudflare.com/profile/api-tokens → 自定义 token → 权限 Account.Turnstile:Edit 和 Account.Workers Scripts:Edit → 在账户资源中包含目标账户。不要引导他们使用 wrangler login。其 OAuth 范围不包括 Account.Turnstile:Edit 或 Account.Workers Scripts:Edit。提供三种方式传递 token,按清洁程度排序:export CLOUDFLARE_API_TOKEN=<token> 然后从该终端重新启动代理。umask 077 && printf '%s' '<token>' > ~/.cf-turnstile-token,然后用 TOKEN=$(cat ~/.cf-turnstile-token) 读取。如果用户选择选项 3(粘贴到聊天中),你可以在等待期间运行步骤 5、6、7(域名、代码库扫描、插入计划)。选项 1 和 2 会重新启动你的会话,因此在这些情况下不要预取状态。认证建立后,重新运行 auth-probe.sh,然后继续到步骤 8。
multiple_accounts:token 覆盖多个账户且 $CLOUDFLARE_ACCOUNT_ID 未设置。展示编号的 accounts 列表。 [等待用户] 然后导出 CLOUDFLARE_ACCOUNT_ID=<选择的> 并重新运行 auth-probe.sh。account_mismatch:设置了 $CLOUDFLARE_ACCOUNT_ID 但不在 token 的账户列表中。展示 accounts 列表,要求用户要么 unset CLOUDFLARE_ACCOUNT_ID,要么将其设置为列表中的一个 ID。auth-probe.sh 在 multiple_accounts 往返后返回 ok,则此步骤已完成。否则脚本已静默选中单个账户,你继续到步骤 5。localhost 和 127.0.0.1。对于生产环境,扫描 package.json 中的 homepage、wrangler.toml、README.md、AGENTS.md、git remote。确认:“我将注册 localhost、127.0.0.1 和 <domain>。是否继续?” [等待用户] 如果未找到生产域名,则询问。[推荐] / [默认跳过] 标记的候选列表;请用户确认(数字、“全部”、“推荐”或列表)。 [等待用户] 如果检测到现有的 CAPTCHA,则显示迁移计划(参见“从其他 CAPTCHA 迁移”)。scripts/widget-create.sh --account-id <id> --name <name> --domains <list> --mode managed。报告 sitekey。secret 保留在环境变量中;绝不要写入磁盘。scripts/worker-deploy.sh --name turnstile-siteverify-<项目slug>,并导出 WIDGET_SECRET。在 status: ok 时报告 Worker URL。如果 set_secret_failed,则 Worker 已部署但 TURNSTILE_SECRET_KEY 未设置在该 Worker 上;向用户展示错误,然后使用 echo "$WIDGET_SECRET" | npx wrangler secret put TURNSTILE_SECRET_KEY --name <返回的 worker_name> 重试,然后再运行验证。success === true 条件。现有处理程序逻辑保持不变。”询问“是” / “展示”。 [等待用户] 如果“展示”,打印统一的 diff 并再次询问。不要提议替代行为(邮件投递、自定义后端)。scripts/validate.sh。报告每个检查项的通过情况。如果任何一项失败,向用户展示错误并停止。 [如果任何失败,等待用户].claude/skills/turnstile-spin/SKILL.md 以便在后续任务中重用?默认是。” [等待用户] 然后运行 scripts/persist-skill.sh --path <代理特定路径>。wrangler secret put(worker-deploy.sh 脚本处理此操作)。sudo 或未经询问安装全局包。Spin 通过一个托管 Worker 验证 Turnstile token,然后才运行用户现有的表单处理程序。其他一切均不在范围内:
success === true 时执行)。不要提议 Resend、Mailchannels、SMTP、mailto。templates/worker/ 下捆绑的标准 Worker 模板。不要编写新的 Worker。不要添加功能(速率限制、自定义路由、第三方集成)。success: true/false。clearance_level !== no_clearance,siteverify 是可选的,Spin 不适用。引导用户并退出。如果用户告诉你他们已经有一个 Turnstile widget 设置好,并且想要连接 siteverify 而不轮换 sitekey(例如“我有一个 sitekey 但 siteverify 从未工作过”、“针对我现有的 widget <sitekey> 设置 Spin”):
scripts/fetch-secret.sh --account-id <id> --sitekey <key> 获取 widget 元数据。根据 status 分支:ok:从响应中读取 secret、clearance_level 和 domains。确认 domains 包含用户的生产主机名;如果不包含,在继续前指出此差距。missing_read_scope:告诉用户向 token 添加 Account.Turnstile:Read,或者退回到要求用户粘贴 secret。在粘贴路径中,你没有 clearance_level 或 domains;请用户确认两者。clearance_level:no_clearance:标准恢复(部署 Worker,连接 siteverify)。data-action="turnstile-spin-v1" 的请求上,Dashboard 的 Deployment 列将从 Manual 变为 Spin。当将现有表单连接到 Worker 时(步骤 10),约定是:门控,不要替换。 用户的现有提交处理程序继续执行其原有的操作。Spin 仅在之前添加一个验证步骤。
form.addEventListener("submit", async (e) => {
e.preventDefault();
const token = /* 读取 cf-turnstile-response */;
const result = await fetch(WORKER_URL, { method: 'POST', body: JSON.stringify({ token }) });
const data = await result.json();
if (!data.success) return; // 显示失败
// 现有的处理程序逻辑在这里运行,保持不变
});
如果现有的处理程序是存根,Spin 会使其成为基于 success 门控的存根。用户以后可以替换这个存根;那不是 Spin 的工作。
在步骤 6 的代码库扫描期间,还要查找现有的 reCAPTCHA 或 hCaptcha。如果找到,将步骤 7 切换为迁移计划。
检测信号:
https://www.google.com/recaptcha/api.js、class="g-recaptcha"、data-sitekey="6L..."、后端 POST 到 /recaptcha/api/siteverifyhttps://js.hcaptcha.com/1/api.js、class="h-captcha"、后端 POST 到 https://hcaptcha.com/siteverify替换:
https://challenges.cloudflare.com/turnstile/v0/api.js(async defer)。class="g-recaptcha" / class="h-captcha" 的 div 替换为 class="cf-turnstile",更新 data-sitekey 为新的 Turnstile sitekey,添加 data-action="turnstile-spin-v1"。g-recaptcha-response 变为 cf-turnstile-response。RECAPTCHA_SECRET / HCAPTCHA_SECRET 环境变量。需要向用户展示的边缘情况:
success === false 时拒绝。action= 值。 保留用户传递给 grecaptcha.execute 的任何自定义 action 作为 widget 上的 data-action。仅当不存在自定义 action 时使用 turnstile-spin-v1。| 情况 | 操作 | |
|---|---|---|
wrangler 未安装 | 安装路径:npm install --save-dev wrangler(Node 项目)或 npm install -g wrangler(其他方式) | |
| 多个 Cloudflare 账户 | scripts/auth-probe.sh 返回所有账户;请用户选择,导出 CLOUDFLARE_ACCOUNT_ID | |
| Cloudflare Pages 项目 | 仍然部署托管 Worker,或者建议使用 Pages Plugin | |
EXPECTED_HOSTNAME 不匹配 | 通过 PUT 而非 PATCH 更新 widget 域名(PATCH 返回 10405 Method not allowed):curl -X PUT .../widgets/$SITEKEY -d '{"name":"...","mode":"managed","domains":[...]}' | |
| Worker 名称冲突 | worker-deploy.sh 自动使用哈希后缀重试 | |
| Token 在流程中过期 | 停止,重新运行 scripts/auth-probe.sh,提示用户提供新的凭据 | |
步骤 11 返回 missing-input-secret | Secret 未传播。重新设置:`echo "$WIDGET_SECRET" \ | npx wrangler secret put TURNSTILE_SECRET_KEY --name <worker-deploy.sh 输出中的 worker_name>,等待 10 秒,重新验证。使用 worker-deploy.sh 返回的 worker_name 字段;不要依赖 $WORKER_NAME` 环境变量。 |
worker-deploy.sh 返回 set_secret_failed | Worker 已部署但 secret 未设置。仅使用返回的 worker_name 重新运行 secret-put:`echo "$WIDGET_SECRET" \ | npx wrangler secret put TURNSTILE_SECRET_KEY --name <worker_name>。向用户展示 detail` 字段——它携带 wrangler 错误信息。 |
你编写的每个代码片段都必须包含 data-action="turnstile-spin-v1"。账户级别的聚合遥测,永远不是用户级别的。Cloudflare 使用它来测量激活情况。如果用户移除了该属性,集成仍然正常工作;只是丢失了分析分段。