
Cloudflare Turnstile 集成模式实战指南从表单接入到服务端验证的完整方案【免费下载链接】skillsSkills Catalog for Codex项目地址: https://gitcode.com/GitHub_Trending/skills4/skills本篇指南以 Cloudflare 的cloudflare-deploy技能仓库中 Turnstile 参考文档patterns.md为核心骨架系统讲解 Turnstile无需传统验证码图片的智能 CAPTCHA 替代方案在真实 Web 项目中的集成模式。你将掌握隐式/显式渲染两种接入方式、React/Vue/Svelte 等主流框架的封装写法、Workers 与 Pages Functions 的服务端验证调用链以及预清障Pre-Clearance、令牌过期刷新等高级模式与测试环境隔离策略。一、集成前置理解 Turnstile 的渲染与验证模型Turnstile 的定位是用户友好的 CAPTCHA 替代方案它利用浏览器行为、设备指纹与机器学习在后台完成人机验证绝大多数用户无需点击任何验证码图片。所有集成模式都建立在两条核心机制之上客户端渲染令牌加载api.js后Turnstile 在页面内生成验证令牌token令牌通过隐藏字段或 JavaScript 回调获取服务端强制校验任何客户端产出的令牌都必须由服务端调用siteverify接口二次验证单靠前端判断永远不够——这是整个模式体系的底线约束详见 gotchas.md。从仓库的 SKILL.md 决策树可以看到Turnstile 在 Cloudflare 安全体系中被归类为CAPTCHA 替代方案security → turnstile适合为表单、登录、评论等场景提供无感人机校验。令牌本身有三条硬性约束所有模式都必须围绕它们设计有效期 5 分钟超过即失效一次性使用每个令牌只能被siteverify成功验证一次必须服务端验证客户端验证可被轻易绕过。二、表单集成两种渲染方式的完整写法2.1 隐式渲染Implicit Rendering零 JavaScript隐式渲染适合页面加载即出现验证控件的传统表单。只需两步引入脚本 在表单内放一个classcf-turnstile的容器。!DOCTYPE html html head script srchttps://challenges.cloudflare.com/turnstile/v0/api.js async defer/script /head body form action/submit methodPOST input typeemail nameemail required div classcf-turnstile>script srchttps://challenges.cloudflare.com/turnstile/v0/api.js?renderexplicit/script script let widgetId window.turnstile.render(#container, { sitekey: YOUR_SITE_KEY, callback: (token) console.log(Token:, token) }); form.addEventListener(submit, async (e) { e.preventDefault(); const token window.turnstile.getResponse(widgetId); if (!token) return; // 验证尚未完成阻止提交 const response await fetch(/submit, { method: POST, body: JSON.stringify({ cf-turnstile-response: token }) }); if (!response.ok) window.turnstile.reset(widgetId); // 失败后重置换取新令牌 }); /script这段代码演示了显式渲染的三个关键动作提交前用getResponse()判断令牌是否就绪、把令牌放入请求体、提交失败时用reset()让用户重新完成验证。注意令牌是一次性的每次失败重试都必须先重置再获取新令牌对应timeout-or-duplicate错误的解法详见 gotchas.md。三、框架集成React / Vue / Svelte 的组件化写法3.1 React使用官方社区组件推荐使用marsidev/react-turnstile令牌通过onSuccess回调进入 React 状态提交按钮在令牌就绪前保持禁用避免无效提交。import { useState } from react; import Turnstile from marsidev/react-turnstile; export default function Form() { const [token, setToken] useStatestring | null(null); return ( form onSubmit{async (e) { e.preventDefault(); if (!token) return; await fetch(/api/submit, { method: POST, body: JSON.stringify({ cf-turnstile-response: token }) }); }} Turnstile siteKeyYOUR_SITE_KEY onSuccess{setToken} / button disabled{!token}Submit/button /form ); }若要在 Next.js App Router 中使用必须把组件标记为客户端组件use client并在useEffect中手动调用window.turnstile.render()、在清理函数中remove()避免 SSR 阶段访问不到window以及组件重挂载导致令牌丢失详见 gotchas.md 中的 React: Widget Re-mounting 与 Next.js: SSR Hydration 两节。3.2 Vue 与 Svelte一行接入!-- Vue: npm install vue-turnstile -- VueTurnstile :site-keySITE_KEY successtoken $event / !-- Svelte: npm install svelte-turnstile -- Turnstile siteKey{SITE_KEY} on:turnstile-callback{(e) token e.detail.token} /Vue 通过success事件拿到令牌Svelte 通过on:turnstile-callback读取事件详情中的token。需要特别留意的是SPA 导航清理组件卸载时应调用window.turnstile.remove(widgetId)Vue 的onBeforeUnmount、React 的useEffect清理函数否则会遗留孤儿 widget详见 gotchas.md。四、服务端验证Workers 与 Pages Functions 的标准调用链服务端验证是必须的一环。统一调用https://challenges.cloudflare.com/turnstile/v0/siteverify请求体包含secret密钥绝不可暴露到客户端、response令牌与可选的remoteip客户端 IP推荐携带以增强安全性接口定义见 api.md。4.1 Cloudflare Workersinterface Env { TURNSTILE_SECRET: string; } export default { async fetch(request: Request, env: Env): PromiseResponse { if (request.method ! POST) { return new Response(Method not allowed, { status: 405 }); } const formData await request.formData(); const token formData.get(cf-turnstile-response); if (!token) { return new Response(Missing token, { status: 400 }); } // Validate token const ip request.headers.get(CF-Connecting-IP); const result await fetch(https://challenges.cloudflare.com/turnstile/v0/siteverify, { method: POST, headers: { Content-Type: application/json }, body: JSON.stringify({ secret: env.TURNSTILE_SECRET, response: token, remoteip: ip }) }); const validation await result.json(); if (!validation.success) { return new Response(CAPTCHA validation failed, { status: 403 }); } // Process form... return new Response(Success); } };关键点TURNSTILE_SECRET通过 Workers 的环境变量Env接口注入通过wrangler secret put或.dev.vars配置环境变量管理详见 wrangler/configuration.md。remoteip使用 Workers 专有的CF-Connecting-IP请求头拿到真实客户端 IP——这是 gotchas.md 强调的IP 地址转发要点若后端在其他代理之后则改用X-Forwarded-For的首个地址。4.2 Cloudflare Pages FunctionsPages Functions 与 Workers 模式完全一致只是通过ctx获取环境变量与请求对象// functions/submit.ts - same pattern as Workers, use ctx.env and ctx.request export const onRequestPost: PagesFunction{ TURNSTILE_SECRET: string } async (ctx) { const token (await ctx.request.formData()).get(cf-turnstile-response); // Validate with ctx.env.TURNSTILE_SECRET (same as Workers pattern above) };此外仓库还提供了开箱即用的 Pages 插件方案cloudflare/pages-plugin-turnstile在functions/_middleware.ts中声明即可让整个站点路由都经过验证详见 configuration.md// functions/_middleware.ts import turnstilePlugin from cloudflare/pages-plugin-turnstile; export const onRequest turnstilePlugin({ secret: YOUR_SECRET_KEY, onError: () new Response(CAPTCHA failed, { status: 403 }) });4.3 siteverify 的响应与错误码验证响应中的success字段为布尔值失败时error-codes数组会给出具体原因。常见错误码与处理建议完整表格见 api.md错误码含义处理建议missing-input-secret未传secret检查请求体是否包含密钥invalid-input-secret密钥错误核对控制台中的密钥与环境变量missing-input-response未传令牌检查隐藏字段名是否为cf-turnstile-responseinvalid-input-response令牌无效/格式错误从 widget 重新获取令牌timeout-or-duplicate令牌过期5 分钟或重复使用重新生成令牌每个令牌只验证一次internal-errorCloudflare 服务端错误指数退避重试bad-request请求格式错误检查 JSON / 表单编码五、高级模式预清障与令牌过期刷新5.1 Pre-ClearanceInvisible进入页面先完成验证对于低风险但希望零交互的场景可以在页面加载时就用size: invisible的 widget 在后台完成一次验证并缓存令牌验证通过后再展示表单。用户在提交时无需再等待验证体验接近无感。div idturnstile-precheck/div form idprotected-form styledisplay: none; button typesubmitSubmit/button /form script srchttps://challenges.cloudflare.com/turnstile/v0/api.js?renderexplicit/script script let cachedToken null; window.onload () { window.turnstile.render(#turnstile-precheck, { sitekey: YOUR_SITE_KEY, size: invisible, callback: (token) { cachedToken token; document.getElementById(protected-form).style.display block; } }); }; /script从源码结构看该模式基于显式渲染 隐藏 widget 实现callback中拿到令牌后立即展示表单令牌已缓存在cachedToken中供提交时使用。注意此模式与execution: execute、appearance: execute等配置组合可以进一步推迟验证到真正需要时选项语义见 configuration.md。由于令牌有效期 5 分钟若用户停留过久提交前需重新验证见 5.2。5.2 令牌过期自动刷新令牌超过 5 分钟即失效。refresh-expired设为manual时配合expired-callback主动重置 widget 换取新令牌保证用户提交时令牌始终有效let widgetId window.turnstile.render(#container, { sitekey: YOUR_SITE_KEY, refresh-expired: manual, expired-callback: () { console.log(Token expired, refreshing...); window.turnstile.reset(widgetId); } });refresh-expired共有三档详见 configuration.mdauto默认过期自动刷新最省心、manual应用自行在expired-callback中调用reset()、never不刷新仅触发expired-callback适用于必须在验证后短时间内完成提交的场景。六、测试策略环境隔离与官方测试密钥6.1 按环境切换密钥开发与生产必须使用不同的密钥通过环境变量或NODE_ENV判断。Cloudflare 提供了专门用于测试的密钥类型密钥行为测试 Site Key始终通过1x00000000000000000000AAwidget 成功令牌可正常验证测试 Site Key始终拦截2x00000000000000000000ABwidget 可见地失败测试 Site Key强制挑战3x00000000000000000000FF总是展示交互式挑战测试 Secret Key1x0000000000000000000000000000000AA验证测试令牌注意测试密钥在localhost和任意域名下都可用但严禁用于生产环境详见 README.md。6.2 环境感知的密钥加载const SITE_KEY process.env.NODE_ENV production ? YOUR_PRODUCTION_SITE_KEY : 1x00000000000000000000AA; // Always passes const SECRET_KEY process.env.NODE_ENV production ? process.env.TURNSTILE_SECRET : 1x0000000000000000000000000000000AA;生产环境使用TURNSTILE_SECRET环境变量对应 Workers 的Env.TURNSTILE_SECRET或 Pages 的ctx.env.TURNSTILE_SECRET开发环境回退到始终通过的测试密钥。这一模式能有效避免两类高频事故测试密钥被误带上生产、生产密钥在本地开发时被意外消耗详见 gotchas.md 的 Test Keys in Production 一节。建议同时用console.log(Secret loaded:, !!process.env.TURNSTILE_SECRET)确认环境变量已正确注入。七、集成避坑清单Gotchas 精华绝不跳过服务端验证客户端校验可被直接绕过siteverify是唯一可信依据绝不把 secret 发到客户端密钥只能存在于服务端环境变量中令牌单次有效每次提交都要新令牌失败后先reset()再重试否则会收到timeout-or-duplicate处理 5 分钟过期接入expired-callback或使用refresh-expired: autoCSP 白名单页面若启用 Content Security Policy需放行script-src与frame-src中的https://challenges.cloudflare.com完整 CSP 示例见 configuration.md不要在前端调用 siteverifyCORS 会拦截浏览器直连验证接口正确链路是浏览器 → 你的后端 → siteverifywidget 尺寸规划布局normal 为 300×65pxcompact 为 130×120px见 gotchas.md调试手段在回调中打点callback/error-callback/expired-callback/timeout-callback在浏览器 Network 面板确认api.js返回 200、检查 siteverify 的请求与响应并用getResponse()isExpired()检查令牌状态。八、配套资料索引围绕本文涉及的主题可继续深入阅读仓库内以下参考文档turnstile/README.md整体概览、widget 类型、快速上手与测试密钥表turnstile/configuration.md脚本加载方式、完整配置对象、HTML data 属性对照表、CSP 与框架级接入turnstile/api.md客户端 JavaScript API 全签名、回调类型、siteverify 请求/响应结构与错误码表turnstile/gotchas.md常见错误、框架陷阱React 重挂载 / StrictMode 双渲染 / SSR、网络与安全、限制表与调试方法wrangler/configuration.mdWorkers 环境变量与密钥配置方式SKILL.mdCloudflare 平台产品决策树了解 Turnstile 在安全体系中的定位。本文所有代码与结论均以仓库内skills/.curated/cloudflare-deploy/references/turnstile/下四份文档及配套参考为准可直接复制用于 Workers、Pages Functions 与主流前端框架的 Turnstile 接入。【免费下载链接】skillsSkills Catalog for Codex项目地址: https://gitcode.com/GitHub_Trending/skills4/skills创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考