Remix 3 的 CSRF 防护中间件怎么配置 📅 发布时间:2026/9/12 3:31:28 👁 浏览次数: Remix 3 的 CSRF 防护中间件怎么配置【免费下载链接】remixThe fully-stacked web framework项目地址: https://gitcode.com/GitHub_Trending/re/remix在一个基于fetch-router的 Remix 3 应用中POST、PUT、PATCH、DELETE这类会改变状态的请求默认没有任何防跨站请求伪造CSRF的屏障。本文的目标是完成一件具体的事在路由的中间件链里启用remix/middleware/csrf提供的csrf()中间件让携带 session cookie 的危险方法请求必须同时通过来源校验 同步化令牌比对才能放行并知道怎样验证配置确实生效。仓库中 remix 包的版本 当前为3.0.0-rc.2要求 Node24.3.0安装命令是文档给出的npm i remixCSRF、Session、Cookie 相关模块都随remix包一起提供。前提session 中间件必须先于 csrf 运行csrf()的令牌存储在服务端 session 里因此它硬性依赖session()中间件先执行。如果你把csrf()放在session()前面或完全漏掉 session 中间件中间件会直接抛出错误csrf middleware requires session() middleware to run before it见 csrf 中间件实现。session cookie 还必须是签名的session-middleware 的 README 明确说明session cookies must be signed以防止客户端篡改会话数据。如果令牌通过隐藏表单字段提交还需要formData()中间件把请求体解析出来否则_csrf字段读不到——token 表单字段来源在 README 中标注了这条依赖。配置步骤挂载中间件并注入令牌完整的最小配置来自 csrf-middleware README 的 Usage 示例import { createCookie } from remix/cookie import { createRouter } from remix/router import { createCookieSessionStorage } from remix/session-storage/cookie import { session } from remix/middleware/session import { csrf, getCsrfToken } from remix/middleware/csrf let sessionCookie createCookie(__session, { secrets: [secret1] }) let sessionStorage createCookieSessionStorage() let router createRouter({ middleware: [session(sessionCookie, sessionStorage), csrf()], }) router.get(/form, (context) { let token getCsrfToken(context) return new Response( form methodpost action/submit input typehidden name_csrf value${token} / button typesubmitSubmit/button /form ) })需要按自己项目替换的只有两处secrets: [secret1]换成你自己的签名密钥session-middleware 的示例 用了secrets: [s3cr3t]并建议配置secure: true, sameSite: lax以及表单页面换成你自己的路由。getCsrfToken(context)的语义是取 session 里的令牌没有就创建一个所以渲染任何含危险方法表单的页面时调用一次即可令牌会随响应里的 session cookie 持久化。中间件顺序方面仓库内的 timeboxer 示例应用 展示了一个更完整的实际写法把表单解析放在 csrf 之前export const router createRouter({ middleware: [ session(sessionCookie, sessionStorage), formData(), csrf(), // ...其余业务中间件 ], })其中 session 配置 使用环境变量SESSION_SECRET作为 cookie 签名密钥非测试环境下缺失会直接抛错SESSION_SECRET is required——如果你的会话密钥也来自环境变量需要保证它先于应用启动就已设置。令牌从哪里读、往哪里传对不安全方法POST、PUT、PATCH、DELETEcsrf()按以下顺序查找提交的令牌见 README 的 Token Sources 一节 与 实现请求头X-Csrf-Token、X-Xsrf-Token、Csrf-Token按此顺序表单字段_csrf依赖formData()中间件解析请求体查询参数_csrf文档给出的立场很明确请求头和隐藏表单字段是推荐传输方式查询参数仅为兼容性保留因为令牌更容易出现在日志、历史和被复制的 URL 里是最弱的选项。文档还提示不要把它作为默认推荐。GET、HEAD、OPTIONS默认属于安全方法不做 CSRF 校验会直接放行这一行为由safeMethods选项控制。来源校验与可选配置项csrf()在令牌比对之外还做来源校验。默认行为当请求带Origin或Referer头时按同源校验allowMissingOrigin默认为true即两个来源头都缺失时请求仍然通过只要令牌有效。CsrfOptions 接口 支持的配置项选项默认值用途tokenKey_csrfsession 中存放令牌的键fieldName_csrf读取令牌的表单字段名headerNames[X-Csrf-Token, X-Xsrf-Token, Csrf-Token]依次检查的头部名safeMethods[GET, HEAD, OPTIONS]不校验的 HTTP 方法origin同源校验允许的跨域来源可为字符串、正则、数组或回调函数allowMissingOrigintrue是否放行缺少Origin/Referer的请求value默认查找逻辑自定义令牌提取函数onError内置 403 响应自定义拒绝响应如果你的部署希望强制要求危险请求必须携带来源头把allowMissingOrigin设为false如果表单会来自另一个已知域名通过origin传入该域名、匹配正则或数组。如何验证配置生效仓库的 timeboxer 安全测试 就是官方给出的验证方式它覆盖了拒绝和放行两个方向可以直接照此手工验证应被拒绝的请求——带合法 session cookie 但不带令牌或带错误令牌的POST/PUT/DELETE响应应为403且响应体精确等于见测试中的断言 assertCsrfRejectionForbidden: missing CSRF token或Forbidden: invalid CSRF token来源非法时的响应体是Forbidden: invalid CSRF origin见 实现中的默认错误响应以上三段文案在未配置onError时固定如此。应被放行的请求——先从页面里提取渲染出的input name_csrf令牌和 session cookie再带着该令牌提交测试里注册接口带有效令牌返回303创建接口返回201。一个可用的手工流程等价于测试中的做法GET一个会渲染_csrf隐藏字段的页面从 HTML 中提取name_csrf的value并记录响应Set-Cookie中的 session cookie用该 cookie 向同一动作地址发POST不带_csrf字段预期得到403和Forbidden: missing CSRF token再发一次并带上_csrf字段或X-Csrf-Token头预期进入正常业务逻辑测试中的成功状态码303/201取决于路由自身不代表固定值。边界与限制文档强调同步化令牌才是csrf()的主防线Origin/Referer检查只是附加信号不能当作唯一保护。如果你的部署能稳定依赖Sec-Fetch-Site和Origin头cop()cop-middleware提供的无令牌跨源防护可能是更合适的选择也可以在csrf()之前叠加一层cop()做提前拦截。README 的原话是如果部署能保证无令牌模型的全部前提这个中间件是可选的。令牌比对使用恒定时间比较实现constantTimeEqual避免时序侧信道令牌由crypto.getRandomValues生成 32 字节随机数。更上层的防护思路cookie 签名密钥轮换、session 生命周期管理、CORS 不等于 CSRF 防护见 docs/guides 的 Auth, Sessions, and Security 章节其中明确建议session 中间件先于csrf()运行表单解析先于_csrf令牌提取。【免费下载链接】remixThe fully-stacked web framework项目地址: https://gitcode.com/GitHub_Trending/re/remix创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考