跳转到正文

CSRF 防护 ​

此中间件同时检查 Origin 和 Sec-Fetch-Site 请求头,防止 CSRF 攻击。任一验证通过就允许请求。

中间件仅验证满足以下条件的请求:

  • 使用不安全的 HTTP 方法(非 GET、HEAD 或 OPTIONS)
  • 内容类型可由 HTML 表单发送(application/x-www-form-urlencoded、multipart/form-data 或 text/plain)

旧浏览器若不发送 Origin 请求头,或者环境中的反向代理移除了该头部,此中间件可能无法正常工作。在这些环境中,请使用其他 CSRF 令牌方式。

导入 ​

ts
import { Hono } from 'hono'
import { csrf } from 'hono/csrf'

用法 ​

ts
const app = new Hono()

// Default: both origin and sec-fetch-site validation
app.use(csrf())

// Allow specific origins
app.use(csrf({ origin: 'https://myapp.example.com' }))

// Allow multiple origins
app.use(
  csrf({
    origin: [
      'https://myapp.example.com',
      'https://development.myapp.example.com',
    ],
  })
)

// Allow specific sec-fetch-site values
app.use(csrf({ secFetchSite: 'same-origin' }))
app.use(csrf({ secFetchSite: ['same-origin', 'none'] }))

// Dynamic origin validation
// It is strongly recommended that the protocol be verified to ensure a match to `$`.
// You should *never* do a forward match.
app.use(
  '*',
  csrf({
    origin: (origin) =>
      /https:\/\/(\w+\.)?myapp\.example\.com$/.test(origin),
  })
)

// Dynamic sec-fetch-site validation
app.use(
  csrf({
    secFetchSite: (secFetchSite, c) => {
      // Always allow same-origin
      if (secFetchSite === 'same-origin') return true
      // Allow cross-site for webhook endpoints
      if (
        secFetchSite === 'cross-site' &&
        c.req.path.startsWith('/webhook/')
      ) {
        return true
      }
      return false
    },
  })
)

选项 ​

optional origin: string | string[] | Function ​

指定 CSRF 防护允许的源。

  • string:单个允许的源(如 'https://example.com')
  • string[]:允许的源数组
  • Function:自定义处理器 (origin: string, context: Context) => boolean,用于灵活验证源和实现绕过逻辑

默认值:仅允许与请求 URL 相同的源

函数处理器接收请求的 Origin 请求头值和请求上下文,可以根据路径、头部或其他上下文数据等请求属性动态验证。

optional secFetchSite: string | string[] | Function ​

指定基于 Fetch Metadata 的 CSRF 防护允许的 Sec-Fetch-Site 请求头值。

  • string:单个允许的值(如 'same-origin')
  • string[]:允许的值数组(如 ['same-origin', 'none'])
  • Function:自定义处理器 (secFetchSite: string, context: Context) => boolean,用于灵活验证

默认值:仅允许 'same-origin'

标准 Sec-Fetch-Site 值:

  • same-origin:来自同源的请求
  • same-site:来自同一站点(不同子域)的请求
  • cross-site:来自不同站点的请求
  • none:并非来自网页的请求(如浏览器地址栏或书签)

函数处理器接收请求的 Sec-Fetch-Site 请求头值和请求上下文,可以根据请求属性动态验证。

基于 MIT 许可证发布。