# @dxv-systems/turnstile 中文文档

规范地址：https://npmcn.com/package/%40dxv-systems/turnstile/

版本：0\.3\.2
npm 元数据更新时间：2026-11-09T19:47:25.537Z
中文译文更新时间：2026-11-13T02:01:18.397Z
软件包许可：MIT

本文由上游 README 翻译，可能存在偏差，请结合原文核对 API、命令与配置。版权与许可归原作者所有。

原始 npm 页面：https://www.npmjs.com/package/%40dxv-systems/turnstile
原文对照：https://npmcn.com/package/%40dxv-systems/turnstile/?lang=original
项目主页：https://github.com/dxv-systems/dxv-packages#readme
源码仓库：https://github.com/dxv-systems/dxv-packages

## 关键信息（来自 npm 元数据）

- 包体积（解压后）：20.1 kB，12 个文件
- 模块格式：CommonJS
- TypeScript 类型：包内自带
- Node.js 要求：\>=20\.0\.0
- 运行依赖：0 个
- peer 依赖：react \>=18，express \>=4
- 首次发布：2026-08-19T14:22:18.836Z
- 最新版本发布：2026-11-09T19:47:25.378Z
- 近 30 天下载量：9807（2026-10-13 至 2026-11-11，npm 官方下载统计）
- 已发布版本数：6（近 12 个月 6 个）

## 中文简介

Cloudflare Turnstile — 现场验证核心, Express and Next.js 路由守护, 以及反应部件

## 安装

```sh
npm install @dxv-systems/turnstile
```

也可以使用：`pnpm add @dxv-systems/turnstile`、`yarn add @dxv-systems/turnstile`、`bun add @dxv-systems/turnstile`

## README

# @dxv-系统/翻转

用于服务器和客户端的 Cloudflare Turnstile: `/siteverify` 核心,用于 Express 和 Next.js App 路由器的路由保护,以及一个反应部件.

```bash
npm i @dxv-systems/turnstile
```

## 入境点

| 导入 | 目录 |
| --- | --- |
| `@dxv-systems/turnstile` | 核心 : `verifyTurnstileToken`, (中文(简体) ), `evaluateTurnstile`, (中文(简体) ), `clientIp`, (中文(简体) ), `turnstileHeaders`, (中文(简体) ), `TURNSTILE_HEADER`, (中文(简体) ), `TURNSTILE_TEST_SITE_KEY` |
| `@dxv-systems/turnstile/express` | `requireTurnstile` 中间软件 |
| `@dxv-systems/turnstile/next` | `assertTurnstile` 用于获取风格的路由处理器 |
| `@dxv-systems/turnstile/react` | `Turnstile` 部件组件,加 `turnstileHeaders`, (中文(简体) ), `TURNSTILE_HEADER`, (中文(简体) ), `TURNSTILE_TEST_SITE_KEY` |

客户端发送符号在 `X-Turnstile-Token` 请求标题( e)`TURNSTILE_HEADER`) (中文(简体) ).

## 服务器

两名警卫都采取相同的两个选择,并共享一个政策执行,所以他们的行为都是一样的.

| 选项 | 含义 |
| --- | --- |
| `secret` | 例如, 您的曲折密钥 `process.env.TURNSTILE_SECRET_KEY`。 。 。 . `undefined` 是外部生产的有效状态. |
| `failClosed` | 真是个 **没有秘密** 意味着. `true`:以503来否认,而不是服务于无人看守的路线. `false`:没有秘密,没有警卫. |

**快递**

```ts
import { requireTurnstile } from "@dxv-systems/turnstile/express";

app.post("/api/login", requireTurnstile({
  secret: process.env.TURNSTILE_SECRET_KEY,
  failClosed: isProduction(),
}), handler);
```

一个被拒绝的请求得到一个JSON的身体 `{ message }` ,其状况见下表.

**Next.js App路由器**

```ts
import { assertTurnstile } from "@dxv-systems/turnstile/next";

export async function POST(req: NextRequest) {
  const denied = await assertTurnstile(req, {
    secret: process.env.TURNSTILE_SECRET_KEY,
    failClosed: isProduction(),
  });
  if (denied) return denied;

  const body = Body.parse(await req.json());
  // ...
}
```

`assertTurnstile` 使用纯网络 `Request` 返回平面 `Response` (或 `null` 请求何时通过)。 它不导入 Next, 所以它在任何抓取式处理器中有效 。 它从不读取尸体, 所以你的处理者仍然可以分析它.

### 否认的

每个案件都未能结案,只有一个故意例外.

| 情况 | 结果 |
| --- | --- |
| 没有秘密, `failClosed: false` | **允许**:明显的"这里没有警卫"状态 |
| 没有秘密, `failClosed: true` | 503和错误日志 |
| 请求时没有令牌 | 403,不打电话 `/siteverify` |
| 驳回质疑 | 403, 登录错误代码 |
| `/siteverify` 无法到达、 时间已过期或返回 5xx | 503:停电不能成为绕道 |
| 秘密错误( O)`invalid-input-secret` (以千美元计) | 503, 不是403: 这是服务器配置错误, 不是机器人 |

`failClosed` 管理一个 **仅无秘密**。一旦一个秘密被设定,一个缺失的代币和一个无法使用的支票都否认.

### 客户端地址

`remoteip` 从 **`x-real-ip`** 只请求标题, 永远不要 `x-forwarded-for`。来电者可以自己发送 `x-forwarded-for`,并代理它附着而不是替换它,所以其最左侧的条目是调用控制. 确定您的反向代理或主机集 `x-real-ip` 到客户端地址.

没有退路。 Cloudflare 得分符号对 `remoteip`因此,一个错误的数值比没有更糟糕。 当信头缺席时,没有 `remoteip` 发送.

### 决定 `failClosed`

这个包从不读取环境. 应用程序如何识别自己的生产部署 不同每个主机,所以你通过 `failClosed` 你自己来 典型的选择 : `true` 在每一个有真正部件和秘密的环境(生产、中转), `false` 在本地开发和丢弃预览环境中.

小心点 `NODE_ENV`: 许多设置 `"production"` 用于每个构件,包括预览,所以它往往本身不是一个可靠的信号.

### 核心 API

需要其它框架时直接使用核心 :

-   `verifyTurnstileToken(token, secret, remoteIp?)` 电话 `/siteverify` 并决心 `{ ok: true }`, (中文(简体) ), `{ ok: false, reason: "rejected", codes }` 或者说 `{ ok: false, reason: "unavailable", detail }`从不扔出.
-   `evaluateTurnstile({ secret, failClosed, token, remoteIp?, path? })` 执行上述政策并决心 `{ allow: true }` 或者说 `{ allow: false, status: 403 | 503, message }`。 。 。 . `path` 仅在日志行中使用.
-   `clientIp(get)` 读取 `x-real-ip` 通过一个标题获取器 `(name) => string | null | undefined`。 。 。 .

## 客户端

```tsx
import { Turnstile, turnstileHeaders, type TurnstileHandle } from "@dxv-systems/turnstile/react";

const [token, setToken] = useState<string | null>(null);
const widget = useRef<TurnstileHandle>(null);

async function onSubmit() {
  try {
    await fetch("/api/login", {
      method: "POST",
      headers: { "Content-Type": "application/json", ...turnstileHeaders(token) },
      body: JSON.stringify({ email, password }),
    });
  } finally {
    widget.current?.reset(); // tokens are single-use
  }
}

<Turnstile ref={widget} siteKey={SITE_KEY} failedMessage="Verification could not load." onToken={setToken} />
<button type="submit" disabled={!token}>Sign in</button>
```

道具 : `siteKey`, (中文(简体) ), `onToken`, (中文(简体) ), `failedMessage`选择 `className` 财务报告和审定财务报表 `theme`。 。 。 . `siteKey` 财务报告和审定财务报表 `failedMessage` 是道具,不是从环境读取:每个捆绑者的公共可变前缀不同(`VITE_*`, (中文(简体) ), `NEXT_PUBLIC_*`),并非每个应用程序都有i18n运行时间.

### 主题

`theme` 默认为 `"light"`不是Cloudflare自己来的 `"auto"`。 。 。 . `"auto"` 遵循操作系统的 `prefers-color-scheme`而不是你的应用的主题。 仅限光的应用程序会向每个访问者显示一个黑暗部件,其OS处于黑暗模式.

过 `"auto"` 如果您的应用遵循系统方案,或 `"dark"` 如果它只是阴暗的。 带有自己的主题切换的应用程序应该通过当前主题, 所以部件在更改时会重新递归 .

### 测试地点密钥

如果没有真正的部件,例如在本地开发中或预览主机名中无法匹配部件域允许列表,请返回到 `TURNSTILE_TEST_SITE_KEY`Cloudflare总是通过钥匙。 这不会削弱生产: 站点密钥是公用, 服务器是闸门, 用测试密钥刻出的一个符号失败 `/siteverify` 对一个真正的秘密.

### 把它包装在你的应用程序

旋转 `./react` 而不是直接将其导入页面:

```tsx
// components/turnstile.tsx
"use client"; // Next only

import { Turnstile as Base, TURNSTILE_TEST_SITE_KEY, type TurnstileHandle } from "@dxv-systems/turnstile/react";

export const Turnstile = forwardRef<TurnstileHandle, { onToken: (t: string | null) => void }>(
  function Turnstile(props, ref) {
    return (
      <Base
        ref={ref}
        siteKey={process.env.NEXT_PUBLIC_TURNSTILE_SITE_KEY || TURNSTILE_TEST_SITE_KEY}
        failedMessage={t("turnstile.failed")}
        {...props}
      />
    );
  },
);
```

包装器提供站点钥匙和副本. 接下来也是 `"use client"` 边界。 包裹是自己的 `"use client"` 指令在建筑中幸存下来,但在建筑后着陆 `"use strict"` 因此,不要依赖它来为您设定边界.

## 模块格式

软件包是通用JS,所以在运行时间不能 `require` 仅依靠无害环境管理。 这个 `./react` 条目不导入服务器代码, 因此 `/siteverify` 逻辑不包含浏览器捆绑.

## 常见问题

### @dxv-systems/turnstile 是什么？

Cloudflare Turnstile — 现场验证核心, Express and Next\.js 路由守护, 以及反应部件

### 如何安装 @dxv-systems/turnstile？

在项目目录运行 npm install @dxv-systems/turnstile，或使用 pnpm add / yarn add / bun add。

### @dxv-systems/turnstile 支持 TypeScript 吗？

支持。包内自带 TypeScript 类型声明（package\.json 声明了 types 入口），安装后即可获得类型提示，无需再安装 @types 包。

### @dxv-systems/turnstile 支持 ESM 还是 CommonJS？

以 CommonJS 形式发布，可以直接 require\(\)；在 ES Module 项目中也可以用 import 引入（Node\.js 会把 module\.exports 作为默认导出）。

### @dxv-systems/turnstile 需要什么版本的 Node\.js？

package\.json 的 engines 字段要求 Node\.js \>=20\.0\.0。版本不符时 npm 默认只给出警告，开启 engine-strict 后会拒绝安装。

### @dxv-systems/turnstile 可以商用吗？

@dxv-systems/turnstile 使用 MIT 许可。宽松许可：允许商业使用、修改和再分发，通常只需在分发时保留原版权与许可声明。以上为概括，不构成法律意见，请以许可原文为准。

### @dxv-systems/turnstile 的下载量有多少？

根据 npm 官方下载统计，@dxv-systems/turnstile 在 2026/10/13 – 2026/11/11 这 30 天内被下载 9,807 次，日均约 327 次。下载量会把 CI 构建、镜像同步和作为其他包依赖的安装一并计入，适合横向比较热度，不能直接等同于使用人数。

### @dxv-systems/turnstile 还在维护吗？

最新版本 0\.3\.2 发布于 2026/11/10（3 天前）；至今共发布 6 个版本，其中过去 12 个月发布了 6 个；首次发布于 2026/08/19。发布频率只是参考信号：功能稳定的工具可能很少需要更新，建议结合源码仓库的 issue 和提交记录判断。

