资讯动态

Cloudflare Turnstile 完整 API 参考:前端 JavaScript API 与 Siteverify 服务端校验实战

发布时间:2026/9/13 5:10:11 来源:尧图企业网站定制
Cloudflare Turnstile 完整 API 参考前端 JavaScript API 与 Siteverify 服务端校验实战【免费下载链接】skillsSkills Catalog for Codex项目地址: https://gitcode.com/GitHub_Trending/skills4/skills本文以 skills/.curated/cloudflare-deploy/references/turnstile/api.md 为骨架系统讲解 Cloudflare Turnstile 的客户端 JavaScript APIwindow.turnstile、Siteverify 服务端校验接口、错误码与 TypeScript 类型定义并结合同目录下的 configuration.md、patterns.md 与 gotchas.md 做纵深补充。读完本文你将能够在 Cloudflare Workers / Pages Functions 或任意后端环境中完整实现「前端渲染 → 取 token → 服务端校验」的闭环并掌握 Token 过期、单次使用、CSP 与密钥安全等关键约束。该文档隶属于本仓库 cloudflare-deploy 技能下的安全产品参考集Security → Turnstile是面向 Agent 与开发者的 Turnstile 集成权威参考属于「CAPTCHA 替代方案」决策分支的落地细节层。一、Turnstile 是什么无感验证与两种核心 APITurnstile 是 Cloudflare 提供的智能 CAPTCHA 替代方案它在后台基于浏览器行为、设备指纹与机器学习信号自动完成访客验证用户几乎无感知不出现传统拼图式验证码。其集成模型由两部分 API 组成客户端 JavaScript API脚本加载后暴露在window.turnstile上负责在页面中渲染 widget、生成 token、重置或移除 widgetSiteverify API服务端把客户端生成的 token 连同 secret 发送到https://challenges.cloudflare.com/turnstile/v0/siteverify进行最终校验这一步是安全闭环的必选项——纯客户端校验可被轻易绕过。阅读顺序见 README.md建议为configuration配置→ api本文→ patterns模式→ gotchas排错。二、脚本加载方式从加载到可用的三种姿势Turnstile 的所有客户端能力都来自api.js加载方式直接影响渲染时机与兼容性本文档「Script Loading」一节给出的三种方式!-- 1. 标准加载页面加载后自动渲染所有 classcf-turnstile 的容器隐式渲染 -- script srchttps://challenges.cloudflare.com/turnstile/v0/api.js async defer/script !-- 2. 显式渲染模式只有调用 window.turnstile.render() 才渲染 -- script srchttps://challenges.cloudflare.com/turnstile/v0/api.js?renderexplicit/script !-- 3. 带加载回调api.js 就绪后触发全局回调 -- script srchttps://challenges.cloudflare.com/turnstile/v0/api.js?onloadonloadTurnstileCallback/script script window.onloadTurnstileCallback () { window.turnstile.render(#container, { sitekey: YOUR_SITE_KEY }); }; /script此外 configuration.md 还补充了两种加载变体!-- 兼容模式暴露 grecaptcha API可作 Google reCAPTCHA 的 drop-in 替代 -- script srchttps://challenges.cloudflare.com/turnstile/v0/api.js?compatrecaptcha/script隐式渲染Implicit不加?render参数页面加载后自动扫描classcf-turnstile元素并按 HTML data 属性渲染适合快速接入显式渲染Explicit加?renderexplicit完全由window.turnstile.render()手动控制渲染时机与位置适合 SPA、条件渲染、受控表单。三、客户端 JavaScript API 全解window.turnstile脚本加载完成后Turnstile JavaScript API 通过全局对象window.turnstile提供五个核心方法。所有方法都以render()返回的widget ID为操作句柄部分方法也接受容器元素。3.1turnstile.render(container, options)—— 渲染 widget参数container为 CSS 选择器字符串或 DOM 元素options为TurnstileOptions配置对象详见本文第六节完整字段见 configuration.md返回string类型的 widget ID供其它 API 方法使用。const widgetId window.turnstile.render(#my-container, { sitekey: YOUR_SITE_KEY, callback: (token) console.log(Success:, token), error-callback: (code) console.error(Error:, code) });3.2turnstile.reset(widgetId)—— 重置 widget清除已生成的 token、重置挑战状态。典型场景是表单校验失败后强制用户重新验证因为 token 单次有效且会过期。// 表单校验失败时重置 if (!validateForm()) { window.turnstile.reset(widgetId); }3.3turnstile.remove(widgetId)—— 彻底移除 widget将 widget 从 DOM 中完全删除。典型场景是 SPA 路由切换、组件卸载时的清理避免孤儿 widget。// 导航清理 window.turnstile.remove(widgetId);3.4turnstile.getResponse(widgetId)—— 获取当前 token返回 widget 当前的有效 token挑战已完成时否则返回undefined。提交前用它判断是否具备可提交的验证凭据。const token window.turnstile.getResponse(widgetId); if (token) { submitForm(token); }3.5turnstile.isExpired(widgetId)—— 判断 token 是否过期检查 token 是否已超过 5 分钟有效期返回布尔值。适合在提交前自检过期即reset()重新生成。if (window.turnstile.isExpired(widgetId)) { window.turnstile.reset(widgetId); }3.6 完整的 TypeScript 接口定义api.md 给出了Turnstile接口的完整 TS 声明可直接作为类型依据interface Turnstile { render(container: string | HTMLElement, options: TurnstileOptions): string; reset(widgetId: string): void; remove(widgetId: string): void; getResponse(widgetId: string): string | undefined; isExpired(widgetId: string): boolean; execute(container?: string | HTMLElement, options?: TurnstileOptions): void; } declare global { interface Window { turnstile: Turnstile; onloadTurnstileCallback?: () void; } }其中execute()配合execution: execute与appearance: execute使用用于「预清除pre-clearance」等延迟执行场景详见 patterns.md。四、回调签名Callback Signatureswidget 生命周期中的关键节点都通过回调暴露API 文档给出了七种标准签名type TurnstileCallback (token: string) void; // 挑战成功token 就绪 type ErrorCallback (errorCode: string) void; // 发生错误携带错误码 type TimeoutCallback () void; // 挑战超时 type ExpiredCallback () void; // token 过期5 分钟 type BeforeInteractiveCallback () void; // 即将展示可交互元素前 type AfterInteractiveCallback () void; // 用户交互完成后 type UnsupportedCallback () void; // 浏览器不支持 Turnstile对应到 options 中为callback、error-callback、timeout-callback、expired-callback、before-interactive-callback、after-interactive-callback、unsupported-callback。调试期可在每个回调里打日志快速定位问题见 gotchas.md 的 Console Logging 模式。五、Siteverify API服务端校验客户端 token 只是「凭据」真正的安全判定在服务端完成。5.1 端点与请求Endpointhttps://challenges.cloudflare.com/turnstile/v0/siteverifyMethodPOSTContent-Typeapplication/json或application/x-www-form-urlencoded请求体结构interface SiteverifyRequest { secret: string; // 你的 secret key绝不能暴露在客户端 response: string; // 来自表单隐藏域 cf-turnstile-response 的 token remoteip?: string; // 用户 IP可选但推荐 idempotency_key?: string; // 幂等校验唯一键可选 }Cloudflare Workers 中的标准调用示例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: request.headers.get(CF-Connecting-IP) }) }); const data await result.json();两个关键工程细节来自 patterns.md 与 gotchas.mdremoteip 取值Cloudflare Workers 用CF-Connecting-IP普通代理后端用X-Forwarded-For的首个 IPCORS 陷阱Siteverify禁止在浏览器端调用会触发 CORS 错误正确路径是「前端 → 自己的后端 → Cloudflare Siteverify」。5.2 响应结构interface SiteverifyResponse { success: boolean; // 校验结果 challenge_ts?: string; // 挑战完成的 ISO 时间戳 hostname?: string; // 解决 widget 时所在的域名 error-codes?: string[]; // successfalse 时的错误码 action?: string; // 来自 widget 配置的 action 名 cdata?: string; // 来自 widget 配置的自定义数据 }成功响应示例{ success: true, challenge_ts: 2024-01-15T10:30:00Z, hostname: example.com, action: login, cdata: user123 }失败响应示例{ success: false, error-codes: [timeout-or-duplicate] }5.3 完整的 Workers 校验闭环将 patterns.md 中的完整示例与 api.md 的接口结合一个可运行的服务端校验如下interface 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 }); } 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 }); } // 校验通过继续处理表单… return new Response(Success); } };Cloudflare Pages Functions 使用同一模式通过ctx.env.TURNSTILE_SECRET与ctx.request取值见 patterns.md。此外还可直接用官方插件cloudflare/pages-plugin-turnstile在functions/_middleware.ts中一行接入。六、错误码速查表Siteverify 返回的error-codes是排错的第一手线索CodeCauseSolutionmissing-input-secret请求未提供 secret在请求中包含secret字段invalid-input-secretsecret 错误到 Dashboard 核对 secret keymissing-input-response未提供 token携带responsetokeninvalid-input-responsetoken 无效或格式错误确认为 widget 生成的合法 tokentimeout-or-duplicatetoken 过期5 分钟或被重复使用重新生成 token且只校验一次internal-errorCloudflare 服务端错误指数退避后重试bad-request请求格式错误检查 JSON / 表单编码其中timeout-or-duplicate是最常见的生产错误根源在于两条硬性约束token 5 分钟过期、token 单次有效详见 gotchas.md。不要把 token 缓存超过 5 分钟也不要对同一 token 重复校验。七、TurnstileOptions 完整类型与配置语义api.md 给出的TurnstileOptions完整定义interface TurnstileOptions { sitekey: string; action?: string; cData?: string; callback?: (token: string) void; error-callback?: (errorCode: string) void; expired-callback?: () void; timeout-callback?: () void; before-interactive-callback?: () void; after-interactive-callback?: () void; unsupported-callback?: () void; theme?: light | dark | auto; size?: normal | compact | flexible; tabindex?: number; response-field?: boolean; response-field-name?: string; retry?: auto | never; retry-interval?: number; language?: string; execution?: render | execute; appearance?: always | execute | interaction-only; refresh-expired?: auto | manual | never; }各关键字段的语义configuration.md 详述sitekey必填Dashboard 分配的站点 keyaction/cData为业务打标action标识场景如logincData携带自定义数据两者都会原样出现在 Siteverify 响应中可用于防重放与审计executionrender默认渲染后立即开始挑战或execute等待手动调用turnstile.execute()appearancealways默认始终可见、executeexecute()前隐藏、interaction-only仅在需要用户交互时显示refresh-expiredauto默认自动刷新过期 token、manual过期后应用自行调用reset()、never不刷新仅触发expired-callbackretry/retry-intervalauto默认自动重试失败挑战间隔默认 8000ms或never不重试触发error-callbackresponse-field/response-field-name是否自动在表单内注入隐藏域默认true隐藏域 name 默认为cf-turnstile-response——服务端正是从这个字段名取 token 的改名后服务端取值需同步修改theme/size/language/tabindex外观与无障碍配置theme支持light/dark/autosize支持normal/compact/flexiblelanguage使用 ISO 639-1 码或auto。隐式渲染HTML data 属性映射隐式渲染时以上 JS 属性通过data-*属性映射完整映射表见 configuration.md这里列出常用部分JavaScript PropertyHTML Data Attribute示例sitekeydata-sitekeydata-sitekeyYOUR_KEYactiondata-actiondata-actionlogincDatadata-cdatadata-cdatasession-123callbackdata-callbackdata-callbackonSuccesserror-callbackdata-error-callbackdata-error-callbackonErrorexpired-callbackdata-expired-callbackdata-expired-callbackonExpiredtimeout-callbackdata-timeout-callbackdata-timeout-callbackonTimeoutthemedata-themedata-themedarksizedata-sizedata-sizecompacttabindexdata-tabindexdata-tabindex0response-fielddata-response-fielddata-response-fieldfalseresponse-field-namedata-response-field-namedata-response-field-nametokenretrydata-retrydata-retryneverretry-intervaldata-retry-intervaldata-retry-interval5000languagedata-languagedata-languageenexecutiondata-executiondata-executionexecuteappearancedata-appearancedata-appearanceinteraction-onlyrefresh-expireddata-refresh-expireddata-refresh-expiredmanual示例div classcf-turnstile >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;8.3 CSP 配置若站点启用了 Content Security Policy必须放行 Turnstile 的脚本与 iframe 域script-src https://challenges.cloudflare.com; frame-src https://challenges.cloudflare.com;完整示例configuration.mdmeta http-equivContent-Security-Policy contentdefault-src self; script-src self https://challenges.cloudflare.com; frame-src https://challenges.cloudflare.com;未配置 CSP 是「widget 不渲染」的常见原因之一gotchas.md。九、常见错误与调试清单9.1 高频问题定位错误现象原因解决Widget 不渲染sitekey 错误、CSP 拦截、file://协议核对 sitekey、为 challenges.cloudflare.com 添加 CSP、改用 http://timeout-or-duplicatetoken 过期或复用生成新 token不缓存超过 5 分钟invalid-input-secretsecret 错误从 Dashboard 核对检查环境变量missing-input-responsetoken 未随请求发送检查表单字段名是否为cf-turnstile-response9.2 客户端调试三件套// 1. 全回调打日志 window.turnstile.render(#container, { sitekey: YOUR_SITE_KEY, callback: (token) console.log(✓ Token:, token), error-callback: (code) console.error(✗ Error:, code), expired-callback: () console.warn(⏱ Expired), timeout-callback: () console.warn(⏱ Timeout) }); // 2. 检查 token 状态 const token window.turnstile.getResponse(widgetId); console.log(Token:, token || NOT READY); console.log(Expired:, window.turnstile.isExpired(widgetId));9.3 常见配置陷阱密钥错配sitekey 与 secret 必须来自同一个 widget混用会直接校验失败测试密钥上生产务必按 8.2 的环境变量方式隔离服务端 secret 未加载检查.env并验证!!process.env.TURNSTILE_SECRETSPA 组件重挂载React 中因状态变化导致 widget 重渲染会丢失 token需用useRef控制生命周期并在卸载时remove()React StrictMode 下要特别注意清理函数。9.4 排错顺序建议先换用测试密钥1x00000000000000000000AA1x0000000000000000000000000000000AA排除 key 问题打开 Network 面板确认api.js返回 200、查看 siteverify 请求与响应体检查是否有 4xx/5xx、CORS 或 CSP 拦截。十、实战要点总结与延伸阅读把本文的 API 知识点串成最小可用闭环加载api.js→render()生成 widget 并拿到 widgetId → 表单提交时getResponse()取 token或依赖自动注入的cf-turnstile-response隐藏域→ 后端调用 Siteverify 校验 → 失败或过期则reset()重新挑战卸载时remove()清理。在此基础上本仓库还提供了配套参考文档可继续深入Turnstile 参考目录Overview、Widget 类型、快速开始、测试密钥Turnstile 配置指南完整 options、data 属性映射、React/Vue/Svelte/Next.js 集成、Pages 插件Turnstile 常用模式表单集成、预清除、token 刷新、服务端校验完整代码Turnstile 排错手册常见错误、框架陷阱、限流约束、调试方法cloudflare-deploy 技能总览安全产品决策树Turnstile 位于 Security 分支以上所有文档与示例代码均可直接在仓库内查看与复用无需额外安装任何依赖。【免费下载链接】skillsSkills Catalog for Codex项目地址: https://gitcode.com/GitHub_Trending/skills4/skills创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

读完文章,也想定制专属网站?

尧图设计师 24 小时内与您沟通定制方案

免费获取报价