# @csrf-armor/nextjs 中文文档

规范地址：https://npmcn.com/package/%40csrf-armor/nextjs/

版本：1\.4\.8
npm 元数据更新时间：2026-10-05T22:39:25.696Z
中文译文更新时间：2026-11-11T03:17:18.340Z
软件包许可：MIT

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

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

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

- 包体积（解压后）：83.6 kB，21 个文件
- 模块格式：ES Module
- TypeScript 类型：包内自带
- Node.js 要求：\>=18\.0\.0
- 运行依赖：1 个
- peer 依赖：next ^13\.0\.0 \|\| ^14\.0\.0 \|\| ^15\.0\.0 \|\| ^16\.0\.0，react ^18\.2\.0 \|\| ^19\.0\.0
- 首次发布：2025-06-02T21:03:52.793Z
- 最新版本发布：2026-10-05T22:39:25.359Z
- 近 30 天下载量：21455（2026-10-11 至 2026-11-09，npm 官方下载统计）
- 已发布版本数：19（近 12 个月 8 个）

## 中文简介

Next.js 应用程序的 CSRF 保护中间软件

## 安装

```sh
npm install @csrf-armor/nextjs
```

也可以使用：`pnpm add @csrf-armor/nextjs`、`yarn add @csrf-armor/nextjs`、`bun add @csrf-armor/nextjs`

## README

# @csrf-armor/ nextjs (中文(简体) )

![CSRF Armor](https://cdn.nebz.dev/csrf-armor/logo-light.webp)

[![CI](https://github.com/muneebs/csrf-armor/workflows/CI/badge.svg)](https://github.com/muneebs/csrf-armor/actions/workflows/ci.yml) [![npm version](https://badge.fury.io/js/@csrf-armor%2Fnextjs.svg)](https://badge.fury.io/js/@csrf-armor%2Fnextjs) [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT) [![Next.js](https://img.shields.io/badge/Next.js-13%2B-black.svg)](https://nextjs.org/)

Next.js 13+ 的 CSRF 保护软件: 中间软件、反应提供者和 `useCsrf` 钩. 与 App 路由器, Pages 路由器和服务器动作一起工作. 中间软件只使用Web API,因此运行于边缘跑道.

## 快开始

### 1\. 安装

```bash
npm install @csrf-armor/nextjs
```

### 2\. 保密

```bash
# .env.local — generate with: openssl rand -base64 32
CSRF_SECRET=your-generated-secret
```

### 3\. 增加中间软件

创建 `middleware.ts` 在您的工程根中( 或在 `src/`) (中文(简体) ). 接下来的16岁,你可以命名 `proxy.ts` 和导出 `proxy` 相反;代码相同.

```typescript
import { NextResponse } from 'next/server';
import type { NextRequest } from 'next/server';
import { createCsrfMiddleware } from '@csrf-armor/nextjs';

if (process.env.NODE_ENV === 'production' && !process.env.CSRF_SECRET) {
  throw new Error('CSRF_SECRET is required in production');
}

const csrfProtect = createCsrfMiddleware({
  secret: process.env.CSRF_SECRET,
  cookie: { secure: process.env.NODE_ENV === 'production' },
});

export async function middleware(request: NextRequest) {
  const result = await csrfProtect(request, NextResponse.next());

  // The helper only reports the outcome; you must block failures yourself.
  // On failure result.response is still the NextResponse.next() you passed in.
  if (!result.success) {
    console.warn('CSRF validation failed', {
      method: request.method,
      url: request.url,
      reason: result.reason,
    });
    return NextResponse.json({ error: 'CSRF validation failed' }, { status: 403 });
  }

  return result.response;
}

export const config = {
  matcher: ['/((?!_next/static|_next/image|favicon.ico).*)'],
};
```

### 4\. 增加提供者

```tsx
// App Router: app/layout.tsx
import { CsrfProvider } from '@csrf-armor/nextjs/client';

export default function RootLayout({ children }: Readonly<{ children: React.ReactNode }>) {
  return (
    <html lang="en">
      <body>
        <CsrfProvider>{children}</CsrfProvider>
      </body>
    </html>
  );
}
```

```tsx
// Pages Router: pages/_app.tsx
import type { AppProps } from 'next/app';
import { CsrfProvider } from '@csrf-armor/nextjs/client';

export default function App({ Component, pageProps }: AppProps) {
  return (
    <CsrfProvider>
      <Component {...pageProps} />
    </CsrfProvider>
  );
}
```

### 5\. 送来信

使用 `csrfFetch` 从钩子中取出; 它添加了符号头并取取回了响应中的旋转符号:

```tsx
'use client'; // App Router only
import { useCsrf } from '@csrf-armor/nextjs/client';

export function ContactForm() {
  const { csrfToken, csrfFetch } = useCsrf();

  async function handleSubmit(e: React.FormEvent<HTMLFormElement>) {
    e.preventDefault();
    const data = new FormData(e.currentTarget);
    await csrfFetch('/api/contact', {
      method: 'POST',
      headers: { 'Content-Type': 'application/json' },
      body: JSON.stringify({ message: data.get('message') }),
    });
  }

  return (
    <form onSubmit={handleSubmit}>
      <textarea name="message" required />
      <button type="submit" disabled={!csrfToken}>Send</button>
    </form>
  );
}
```

API 路由不需要额外的代码: 在您的处理器运行之前, 中间软件已经验证了请求 .

## 服务器动作

包含一个隐藏的字段 。 行动必须宣布: `FormData` 参数,即使未使用,因为 Next.js 只发送已声明的参数和符号在窗体数据中运行:

```tsx
'use client';
import { useCsrf } from '@csrf-armor/nextjs/client';
import { saveMessage } from './actions';

export function MessageForm() {
  const { csrfToken } = useCsrf();
  return (
    <form action={saveMessage}>
      <input type="hidden" name="csrf_token" value={csrfToken ?? ''} />
      <input name="message" />
      <button type="submit">Save</button>
    </form>
  );
}
```

```typescript
// actions.ts
'use server';

export async function saveMessage(_formData: FormData) {
  // Only runs if the middleware accepted the token
}
```

## 客户端 API

从 `@csrf-armor/nextjs/client`。 。 。 .

### `<CsrfProvider config?>`

在React状态下保留了指使符,在路由更改和回向/前向导航上重新读取,并从响应头更新.

| `config` 选项 | 默认 | 说明 |
| --- | --- | --- |
| `cookieName` | `'csrf-token'` | Cookie来读信物的 匹配 `cookie.name` 在服务器上. |
| `headerName` | `'x-csrf-token'` | 寄信封的信头 匹配 `token.headerName` 在服务器上. |
| `initialToken` | 无 | 切入开始,例如由服务器提供. |
| `refreshEndpoint` | 当前路径 | URL 已获取以获取新符号 . |

### `useCsrf()`

回返 `{ csrfToken, csrfFetch, updateToken }`数字 :

-   `csrfToken: string | null`: 当前符号
-   `csrfFetch(input, init?)`数字 : `fetch` 发送符号头并存储任何来自响应的新符号
-   `updateToken()`: 从饼干上重新读取符号

外部使用时投掷 `CsrfProvider`。 。 。 .

## 每个路线的不同策略

每个策略创建一个保护者,并选择每个请求:

```typescript
const apiCsrf = createCsrfMiddleware({ strategy: 'signed-token', secret: process.env.CSRF_SECRET });
const webCsrf = createCsrfMiddleware({ secret: process.env.CSRF_SECRET });

export async function middleware(request: NextRequest) {
  const protect = request.nextUrl.pathname.startsWith('/api/') ? apiCsrf : webCsrf;
  const result = await protect(request, NextResponse.next());
  return result.success
    ? result.response
    : NextResponse.json({ error: 'CSRF validation failed' }, { status: 403 });
}
```

给每个守护者一个不同的 `cookie.name` 如果两者都可以适用于同一浏览器.

## 配置

`createCsrfMiddleware()` 接受共享 `CsrfConfig`所有选项都是可选的; `secret` 在生产中需要.

-   [配置参考](https://github.com/muneebs/csrf-armor/blob/main/docs/configuration.md): 每个选项、默认、排除和会话具有约束力(`getSessionId` 接收 `NextRequest`(中文(简体) )
-   [战略](https://github.com/muneebs/csrf-armor/blob/main/docs/strategies.md)
-   [安保指南](https://github.com/muneebs/csrf-armor/blob/main/docs/security.md)

一个完整的示例应用程序,包括用于测试每个策略的攻击者页面,生活在 [`examples/nextjs-app`](https://github.com/muneebs/csrf-armor/tree/main/examples/nextjs-app)。 。 。 .

## 许可证

麻省理工学院 [萨缪尔斯](https://github.com/muneebs)

## 常见问题

### @csrf-armor/nextjs 是什么？

Next\.js 应用程序的 CSRF 保护中间软件

### 如何安装 @csrf-armor/nextjs？

在项目目录运行 npm install @csrf-armor/nextjs，或使用 pnpm add / yarn add / bun add。它还需要宿主项目提供 peer 依赖：next（^13\.0\.0 \|\| ^14\.0\.0 \|\| ^15\.0\.0 \|\| ^16\.0\.0）、react（^18\.2\.0 \|\| ^19\.0\.0）。npm 7 及以上与 pnpm 8 及以上默认会自动安装必需的 peer 依赖，Yarn 需要手动安装。

### @csrf-armor/nextjs 支持 TypeScript 吗？

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

### @csrf-armor/nextjs 支持 ESM 还是 CommonJS？

以 ES Module 形式发布，推荐使用 import 引入。在 CommonJS 项目中，Node\.js 20\.19\+ / 22\.12\+ 可以直接 require\(\) 不含顶层 await 的 ES Module，更早的版本需要改用动态 import\(\)。

### @csrf-armor/nextjs 需要什么版本的 Node\.js？

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

### @csrf-armor/nextjs 可以商用吗？

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

### @csrf-armor/nextjs 的下载量有多少？

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

### @csrf-armor/nextjs 还在维护吗？

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

