gorilla csrf中间件默认只校验不生成token,需手动调用csrf.token(r)注入模板或响应头;关键参数secure、httponly、samesite须正确配置,否则导致403;不同框架token不共享,混用时需统一框架或确保session store一致。

为什么 Gorilla CSRF 中间件默认不生效
它不会自动注入 token 到模板或响应头里,只做校验。你写了 csrf.Protect,但没手动把 csrf.Token(r) 传进 HTML 表单,请求必然 403。
- 中间件只拦截并验证
_csrf字段(或自定义字段),不负责生成、不负责渲染 - 必须在 handler 里显式调用
csrf.Token(r),再通过html/template注入到表单 hidden input 或 meta 标签中 - 如果用 JSON API,得把 token 放进响应头(如
X-CSRF-Token),前端下次请求带上它(headers: { 'X-CSRF-Token': token }) - 注意:token 是 per-session 的,重启服务不影响已发 token,但 session 过期后旧 token 失效
如何正确配置 csrf.Protect 的关键参数
最常踩坑的是 Secure、HttpOnly 和 SameSite 搭配错误,导致 cookie 不被发送或校验失败。
-
Secure: true→ 必须走 HTTPS,开发时设为false,否则本地http://localhost下 cookie 不发送 -
HttpOnly: false→ 必须关掉,否则前端 JS 拿不到 cookie(而 Gorilla 默认从 cookie 读 token,不是 header) -
SameSite: http.SameSiteLaxMode或http.SameSiteStrictMode→ 推荐 Lax,兼容 GET 跳转;Strict 会阻断所有跨站 POST,包括从邮件链接来的提交 - 不要设
Domain除非真要跨子域共享 token;设了却没匹配上,cookie 就不会被浏览器携带
POST 表单提交 403:检查这三处
错误现象:页面能打开,但一提交就 403,控制台看不到明显报错,日志只显示 CSRF token mismatch。
- HTML 表单里漏了
<input type="hidden" name="csrf_token" value="{{.CSRFToken}}">—— 注意 name 必须和Field Name参数一致(默认是csrf_token) - handler 返回模板时没传 token:
tmpl.Execute(w, map[string]interface{}{"CSRFToken": csrf.Token(r)}) - 前端用了 AJAX 但没带 token:GET 请求不用 token,但 POST/PUT/DELETE 都要,且必须是 body 或 header;若用 header 方式,需初始化中间件时加
csrf.HeaderName("X-CSRF-Token")
与 Gin 或 Echo 共存时 token 不共享
Gorilla CSRF 中间件的 token 存在 http.Request.Context() 和底层 cookie 里,和其他框架互不识别。混用框架时不能“共用一套 token”。
立即学习“go语言免费学习笔记(深入)”;
- 如果你在 Gin 路由里调用了 Gorilla 的
csrf.Token(r),会 panic:因为 r 不是*http.Request,而是 Gin 的封装体 - 不同框架的中间件无法共享 session store —— 即使都用
gorilla/sessions,也要确保使用同一个Store实例和相同加密密钥 - 更稳妥的做法:统一用一个框架处理需要 CSRF 保护的路由;或改用标准库
net/http+ Gorilla 组合,避免框架胶水层干扰
真正麻烦的不是配置几行代码,而是 token 生命周期和传输路径必须全程对齐:生成、下发、携带、校验,任一环用错方式(比如该放 header 却塞 body,或该读 cookie 却期待 header),就静默失败。别依赖“它应该自己工作”。










