LOGO 首页 OA教程 ERP教程 模切知识交流 PMS教程 CRM教程 技术文档 其他文档  
 
网站管理员

Cloudflare Turnstile:免费拦截机器人,让验证码几乎无感

admin
2026年7月18日 0:49 本文热度 9

验证码这件事,本来不该这么繁琐

网站刚加上登录框,撞库脚本就找上门。所谓「撞库」,就是机器人拿着泄露的账号密码,一遍遍尝试登录。注册页才上线,假账号也可能批量涌入;评论区一开放,很快就会塞满广告链接。

很多网站会用 reCAPTCHA 应对这类问题:先放一个「我不是机器人」的勾选框,遇到可疑用户,再让对方辨认红绿灯、斑马线。这套流程会打断操作,还依赖 Google,并会收集用户行为数据。超过免费额度后,reCAPTCHA 按调用量收费,流量越大,账单越高。

Turnstile 是 Cloudflare 推出的智能验证码,对用户几乎无感,对开发者免费、不限调用量,也更注重隐私。 你可以把它想成站在网站门口的保安:它先在后台观察这次访问是否正常,只有觉得可疑时,才会请访问者额外确认。大多数真人不需要认图、输字符,甚至感觉不到它的存在。

本文依据 2026 年 7 月的 Cloudflare Turnstile 官方文档[1] 编写。相关功能、参数和控制台界面可能继续调整,请以官方页面为准。

📌 一句话定位:Turnstile = 免费、无限量、无感、隐私友好的 reCAPTCHA 替代方案。

它到底怎么「看出来」你不是机器人?

reCAPTCHA 倾向于给访问者出题,Turnstile 则把大部分检查放在后台。整个过程可以理解为「前端领通行证,服务端验通行证」:

  1. 1. 用户打开页面后,浏览器会加载一小段 Turnstile 的 JavaScript 代码,并自动做一组后台检查。这里的「前端」,就是用户能打开和操作的网页。
  2. 2. Turnstile 会查看浏览器环境是否正常、是否带有自动化工具的特征,再交给 Cloudflare 的模型评估风险。
  3. 3. 风险较低时直接通过,浏览器会拿到一个一次性 token。token 可以理解为一张临时通行证。风险较高时,页面才会出现勾选框,让用户手动确认。
  4. 4. 用户提交表单时,网页会把 token 一起交给你的服务端。这里的「服务端」,就是接收登录、注册等请求的后台程序。服务端再调用 siteverify 接口,请 Cloudflare 检查这张通行证是真是假。

Token 只能使用一次,并会在短时间内过期。 这和一次性门票类似,用过就作废。即使攻击者截获了 token,也不能拿它反复提交请求。因此,每次提交表单时,服务端都要重新校验。对正常用户来说,页面通常只会短暂显示一个小验证框,甚至完全没有可见变化。

三种挂件类型:按场景挑一个

Turnstile 提供三种挂件类型。这里的「挂件(widget)」就是嵌在网页里的验证框,三种类型的主要区别是它是否可见、用户是否需要操作:

类型
用户看到什么
是否需要交互
适合场景
Managed(托管)
默认一个小挂件;风险高才弹勾选框
多数情况无感,少数情况勾一下
登录、注册、评论等通用表单(官方推荐默认
Non-Interactive(非交互)
显示一个正在验证的挂件
完全不用动手
想明确告诉用户这里正在验证,但又不打扰操作
Invisible(隐形)
页面上什么都不显示
完全不用动手
提交按钮、API 调用等不希望出现任何 UI 的场景

如果你不知道该选哪个,直接选 Managed。这是官方推荐的默认选项:普通用户通常无感通过,只有可疑访问才需要点一下,适合登录、注册和评论等大多数场景。

选好类型后,还可以设置挂件什么时候出现。可见挂件(Managed / Non-Interactive)支持三种 appearance(显示方式)

  • • always(默认):页面加载就显示。
  • • execute:调用 turnstile.execute() 后才显示,适合配合表单提交时机。
  • • interaction-only:只有需要用户交互时才显示,大多数用户不会看到挂件。

⚠️ 如果你只是想先把 Turnstile 跑起来,保留默认的 always 即可。appearance 只影响可见挂件,Invisible 类型无论怎么设置都不会显示。

免费额度 & 定价

Turnstile 对所有 Cloudflare 套餐免费,而且不限调用量和域名数量。每验证一次,就算一次调用。Turnstile 不按调用次数计费,也不会在用量超过某个数字后突然开始收费。

项目
免费情况
说明
调用量
无限
不限每月验证次数,不计费
域名数量
不限
一个账户下所有站点都能用
套餐门槛
Free 即可
不需要 Pro / Business / Enterprise
挂件类型
全部可用
Managed / Non-Interactive / Invisible 都免费
隐藏成本
不按请求、不按席位、不按功能收费

reCAPTCHA 虽然提供免费额度,但企业版(reCAPTCHA Enterprise)按验证量收费,参考价格约为每千次 $1,具体以 Google 官方定价为准。网站流量越大,这笔开销就越高。它还依赖 Google,并会收集用户行为数据。

你的域名不需要托管在 Cloudflare,也不需要让网站流量经过 Cloudflare,照样可以接入 Turnstile。你只需要一个 Cloudflare 账户,并在网页和服务端各加入少量代码。

5 分钟快速开始

接入过程只有三步:先在 Cloudflare 创建挂件,再把挂件放进网页,最后让服务端校验验证结果。第三步最重要,不能省略。

第一步:在控制台创建挂件

  1. 1. 打开 Cloudflare 控制台,进入目标站点的 Turnstile
  2. 2. 点击 Add widget(添加挂件),填写名称,并把站点域名加入 Domains
  3. 3. 选一个 Mode(推荐 Managed),保存。

  4. 4. 你会拿到一对密钥,它们的用途不同:
    • • Site Key:相当于挂件的公开编号,放在网页里,被别人看到也没关系。
    • • Secret Key:相当于后台密码,只能放在服务端环境变量中,绝不能写进网页或提交到代码仓库。

如果你只是给一个网站接入 Turnstile,可以跳过下面这段。需要管理很多网站时,才有必要用 API 批量创建挂件:

curl -X POST "https://api.cloudflare.com/client/v4/accounts/$ACCOUNT_ID/challenges/widgets" \
  -H "Authorization: Bearer $CF_API_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "name": "My Login Widget",
    "domains": ["example.com"],
    "mode": "managed"
  }'

第二步:前端嵌入挂件

现在把验证框放进网页。最简单的方法是「隐式渲染」,意思是只在 HTML 里留一个位置,官方脚本会自动把挂件画出来:

<form id="login-form" action="/api/login" method="POST">
  <input type="text" name="username" placeholder="用户名" />
  <input type="password" name="password" placeholder="密码" />


  <div class="cf-turnstile"
       data-sitekey
="YOUR_SITE_KEY"
       data-callback
="onTurnstileSuccess"></div>

  <button type="submit">登录</button>
</form>

<script src="https://challenges.cloudflare.com/turnstile/v0/api.js" defer></script>
<script>
  function
 onTurnstileSuccess(token) {
    // token 已经生成,随表单一起提交即可

    console
.log("Turnstile token:", token);
  }
</script>

上面的写法能满足普通 HTML 表单。如果你的表单由 JavaScript 提交,或者需要自己控制挂件何时出现,再使用下面的「显式渲染」。初次接入时可以先跳过:

<script src="https://challenges.cloudflare.com/turnstile/v0/api.js?render=explicit" defer></script>
<div id="turnstile-widget"></div>

<script>
  window
.onload = () => {
    turnstile.render("#turnstile-widget", {
      sitekey
: "YOUR_SITE_KEY",
      appearance
: "always",
      callback
: (token) => console.log("通过:", token),
      "error-callback"
: (code) => console.error("出错:", code),
      "expired-callback"
: () => console.log("token 已过期"),
    });
  };
</script>

第三步:服务端校验 token(关键!)

网页显示验证通过,不代表这次请求一定可信。 攻击者可以不打开你的网页,直接向登录接口发送请求。服务端必须拿着 Secret Key 调用 siteverify,让 Cloudflare 确认 token 是真的、没过期、也没有被用过。

下面是 TypeScript 示例。它接收 token、Secret Key 和可选的用户 IP,验证成功返回 true,失败返回 false

async function validateTurnstile(
  token
: string,
  secret
: string,
  ip
?: string,
): Promise<boolean> {
  const
 res = await fetch(
    "https://challenges.cloudflare.com/turnstile/v0/siteverify"
,
    {
      method
: "POST",
      headers
: { "Content-Type": "application/json" },
      body
: JSON.stringify({
        secret,
        response
: token,
        ...(ip ? { remoteip: ip } : {}),
      }),
    },
  );
  const
 data = await res.json();
  return
 data.success === true;
}

Cloudflare 不只会返回「成功」或「失败」,还会附带一些信息。刚开始接入时,先关注 success 和 error-codes 就够了:

字段
含义
success
校验是否通过
challenge_ts
挑战完成的时间戳
hostname
提交 token 的域名
action
你自定义的 action 名(用于分析)
cdata
你自定义透传的数据(用于分析)
error-codes
失败时的错误码数组

常见错误码包括:timeout-or-duplicate(token 已过期或使用过)、invalid-input-secret(Secret Key 错误)、invalid-input-response(token 无效)、invalid-input-remoteip(用户 IP 不匹配)。遇到问题时,可以先根据这些错误码定位原因。

实战场景

场景 1:给登录接口加一道人机校验

下面用 Cloudflare Worker 演示完整顺序。代码先检查 Turnstile,确认不是普通机器人后,再检查用户名和密码:

export async function onRequestPost(context: any) {
  const
 { request, env } = context;
  const
 { username, password, token } = await request.json();

  // 1) 先校验 Turnstile

  const
 ip = request.headers.get("CF-Connecting-IP") ?? undefined;
  const
 ok = await validateTurnstile(token, env.TURNSTILE_SECRET_KEY, ip);
  if
 (!ok) {
    return
 new Response(JSON.stringify({ error: "人机验证失败" }), {
      status
: 403,
      headers
: { "Content-Type": "application/json" },
    });
  }

  // 2) 再走你原来的登录校验

  const
 valid = await checkCredentials(username, password);
  if
 (!valid) {
    return
 new Response(JSON.stringify({ error: "账号或密码错误" }), {
      status
: 401,
      headers
: { "Content-Type": "application/json" },
    });
  }

  return
 new Response(JSON.stringify({ message: "登录成功" }), {
    status
: 200,
    headers
: { "Content-Type": "application/json" },
  });
}

请把 Secret Key 存入 Worker 的环境变量(Wrangler vars / .dev.vars),不要直接写在源码里。否则代码一旦公开,别人就能拿走这把「后台钥匙」。

场景 2:与 WAF 和 Bot Management 联动

网站流量变大后,可以把 Turnstile 与 WAFBot Management 配合使用。它们像三道位置不同的门,各自拦截一类风险:

  • • Bot Management / Bot Fight Mode:机器人管理功能,在请求到达网站程序前,先识别并挑战明显的自动化流量。
  • • Turnstile:在关键表单(登录、注册、结账)前再补一道显式验证。
  • • WAF 自定义规则:WAF 是 Web 应用防火墙,可以根据你设置的规则,直接拦截反复验证失败或绕过网页的请求。

常见做法是先用 Bot Score(机器人风险分数)过滤明显的垃圾流量,再在登录页用 Turnstile 检查剩下的可疑请求,最后由 WAF 拦截反复失败等异常行为。个人小站不必一开始就配齐三层,先正确接入 Turnstile 即可。

场景 3:Pre-Clearance(预验证),让老用户全程无感

如果网站有多个页面需要验证,可以让用户验证一次,后续页面无感通行。开启 Pre-Clearance(预验证)后,用户第一次通过挑战时,浏览器会拿到一个在当前会话中有效的凭证。之后访问站内其他受保护页面,就不必重复验证。

这很适合多步结账和分成几页填写的长表单:用户只在第一步接受验证,后续步骤不会再被打断。普通登录或评论表单暂时用不到,可以先跳过。

场景 4:A/B 测试,从 reCAPTCHA 平滑迁移

Cloudflare 提供 reCAPTCHA 兼容模式,方便你逐步迁移。比如先让 10% 的访问使用 Turnstile,其余访问继续使用 reCAPTCHA,这就是「灰度迁移」。对比两边的验证通过率、真人被误拦的比例和表单完成率后,再决定是否全部切换。兼容模式也能减少迁移期间的服务端改动。

成本计算器:为什么它「免费」最值钱

验证码通常按验证次数收费。假设你的网站每月要验证 100 万次表单提交

方案
计费方式(参考官方定价)
月成本估算
Cloudflare Turnstile
完全免费、无限量
$0
reCAPTCHA Enterprise(参考价)
约按每千次评估收费
量级在数百美元/月
hCaptcha Enterprise
企业报价,按量
视合同

以上数字只是估算,请以各厂商最新的官方定价为准。Turnstile 不随验证量增加而收费,无论验证 100 万次还是 1 亿次,直接费用都是 $0。

对独立开发者来说,这意味着不必在安全防护和验证码账单之间权衡。

最佳实践 & 避坑指南

  1. 1. 一定要在服务端校验 token。 网页里的 success 回调只负责更新界面,真正的安全检查由 siteverify 完成。漏掉这一步,攻击者就能绕过挂件,直接请求接口。
  2. 2. Secret Key 只能放在服务端。 用环境变量或 Secrets 管理,不要把它打包进网页代码,也不要提交到 Git。
  3. 3. 不要保存或重复使用 token。 token 只能使用一次,而且很快会过期。用户重新提交表单,或者触发 expired-callback 后,都要重新验证。
  4. 4. 需要更严格的校验时,再加入 remoteip 和 action 你可以同时提交用户 IP,并检查返回的 action 是否与当前操作一致,比如登录请求只能接受 login
  5. 5. 告诉用户验证出了什么问题。 为 error-callbackexpired-callbacktimeout-callback 显示「验证失败,请重试」或「验证已过期」等提示,不要让页面一直转圈。
  6. 6. 不同网站使用不同挂件。 按域名或业务创建独立 widget,方便分别查看数据。即使某个 Secret 泄露,影响也不会扩散到所有网站。
  7. 7. 需要分析数据时,再使用 action 和 cdata 可以给请求加上 loginsignup 等标签,然后在 Turnstile 面板中分别查看登录和注册的通过率。
  8. 8. 不要把 Turnstile 当作唯一防线。 它只能判断访问者是否可能是真人。真人也可能盗号或攻击网站,所以密码校验、权限检查和数据库安全措施仍然不能少。
  9. 9. 有欧盟数据合规要求时,设置数据区域。 创建 widget 时把 region 设为 eu,并在网页脚本中设置 data-region="eu";没有这类要求时,使用默认值 world 即可。
  10. 10. 上线后先观察,再调整。 先用 Managed 默认模式运行一段时间,查看正常用户有没有被误拦,再决定是否加强高风险页面的验证。

Turnstile vs reCAPTCHA:到底差在哪?

维度
Cloudflare Turnstile
Google reCAPTCHA
价格
完全免费、无限量
基础版免费,Enterprise 按量收费
用户感知
多数无感,少数才勾选
勾选框,可疑时要做图片题
隐私
不收集行为数据做广告训练
会收集用户交互数据
依赖
仅需 Cloudflare 账户
需要 Google 服务可用
部署
任意站点(不需走 Cloudflare 代理也能用挂件)
任意站点
数据分析
action / cdata 自定义分析
有自己的后台面板
迁移成本
提供 reCAPTCHA 兼容层,可灰度

如果你更看重低成本、低打扰和隐私保护,Turnstile 是更合适的选择;是否继续使用 reCAPTCHA,则取决于站点对 Google 生态的依赖程度。

上线检查清单

  • • [ ] 已在控制台创建挂件,拿到 Site Key 和 Secret Key
  • • [ ] Site Key 放在网页中,Secret Key 只放在服务端环境变量中
  • • [ ] 已选择挂件类型,不确定时使用 Managed
  • • [ ] 服务端每次都调用 siteverify 校验 token
  • • [ ] 已处理 success=false;需要更严格校验时,再传入 remoteip
  • • [ ] 验证出错、过期或超时时,页面会告诉用户如何重试
  • • [ ] 需要欧盟数据驻留时,已把挂件的 region 设为 eu
  • • [ ] 已在 Turnstile 面板观察通过率和真人被误拦的情况
  • • [ ] 登录鉴权、权限检查和数据库安全仍由网站程序负责

最后的判断

Turnstile 把人机验证的直接成本降到 :不限调用量、不限域名、所有套餐免费,同时很少打扰正常用户。对独立开发者来说,它尤其适合保护登录、注册和评论表单。

Turnstile 只能判断访问者是否可能是真人,不能判断这个人有没有访问权限。 用户通过验证后,网站仍要检查密码和权限,并安全地处理提交的数据。小型网站先做好 Turnstile 的服务端校验,就已经拦住了最常见的自动化请求;流量和风险提高后,再考虑加入 Bot Management 和 WAF。

相关资源

  • • Cloudflare Turnstile 官方文档[1]

引用链接

[1] Cloudflare Turnstile 官方文档: https://developers.cloudflare.com/turnstile/


阅读原文:点击这里


该文章在 2026/7/18 0:49:41 编辑过
关键字查询
相关文章
正在查询...
点晴ERP是一款针对中小制造业的专业生产管理软件系统,系统成熟度和易用性得到了国内大量中小企业的青睐。
点晴PMS码头管理系统主要针对港口码头集装箱与散货日常运作、调度、堆场、车队、财务费用、相关报表等业务管理,结合码头的业务特点,围绕调度、堆场作业而开发的。集技术的先进性、管理的有效性于一体,是物流码头及其他港口类企业的高效ERP管理信息系统。
点晴WMS仓储管理系统提供了货物产品管理,销售管理,采购管理,仓储管理,仓库管理,保质期管理,货位管理,库位管理,生产管理,WMS管理系统,标签打印,条形码,二维码管理,批号管理软件。
点晴免费OA是一款软件和通用服务都免费,不限功能、不限时间、不限用户的免费OA协同办公管理系统。
Copyright 2010-2026 ClickSun All Rights Reserved  粤ICP备13012886号-9  粤公网安备44030602007207号