CSRF 防护
该中间件通过校验 Origin 与 Sec-Fetch-Site 请求头来抵御 CSRF 攻击,只要其中任一校验通过即可放行。
中间件仅会对以下请求进行校验:
- 使用不安全 HTTP 方法(非 GET、HEAD、OPTIONS)
- Content-Type 为 HTML 表单可发送的类型(
application/x-www-form-urlencoded、multipart/form-data或text/plain)
旧版浏览器可能不会发送 Origin 头,或运行在移除了这些头部的反向代理环境中,此时该中间件效果会受限,建议改用其他基于 CSRF Token 的方案。
导入
ts
import { Hono } from 'hono'
import { csrf } from 'hono/csrf'用法
ts
const app = new Hono()
// 默认同时验证 origin 与 sec-fetch-site
app.use(csrf())
// 允许特定来源
app.use(csrf({ origin: 'https://myapp.example.com' }))
// 允许多个来源
app.use(
csrf({
origin: [
'https://myapp.example.com',
'https://development.myapp.example.com',
],
})
)
// 允许指定的 sec-fetch-site 值
app.use(csrf({ secFetchSite: 'same-origin' }))
app.use(csrf({ secFetchSite: ['same-origin', 'none'] }))
// 动态校验来源
// 强烈建议验证协议并确保以 `$` 结尾匹配。
// 切勿使用前缀匹配。
app.use(
'*',
csrf({
origin: (origin) =>
/https:\/\/(\w+\.)?myapp\.example\.com$/.test(origin),
})
)
// 动态校验 sec-fetch-site
app.use(
csrf({
secFetchSite: (secFetchSite, c) => {
// 始终允许同源请求
if (secFetchSite === 'same-origin') return true
// 为 webhook 端点允许跨站请求
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 值及上下文,可据此动态判断是否允许。