csrf中间件必须在路由注册前启用,否则校验失效;token须随表单或x-csrf-token头提交并匹配校验逻辑;静态资源和纯get接口需显式豁免;samesite cookie不能替代csrf token。

CSRF中间件必须在路由注册前启用
Go Web框架(如Gin、Echo)里,csrf.Middleware 或 gorilla/csrf 的中间件如果加在路由之后,所有请求都会绕过校验——因为中间件链已终止。这不是配置错误,是执行顺序问题。
- Gin:必须在
r.Use(csrf.New(...))之后再调用r.GET等注册路由 - Echo:
e.Use(middleware.CSRFWithConfig(...))要放在e.POST前,且不能只挂给某个分组而漏掉登录/支付等关键路径 -
gorilla/mux 用户容易误把
csrf.Protect当成装饰器塞进 handler 链末尾,实际它必须是顶层中间件,否则_csrftoken 不会注入响应头或模板
token必须随表单提交且校验方式要匹配
前端没传 _csrf 字段、传错位置、或后端校验逻辑不一致,都会触发 403。常见现象是“刷新页面能进,点按钮就报错”,本质是 token 生命周期或传输通道不匹配。
- 默认情况下,
gorilla/csrf只从 POST 表单的_csrf字段或X-CSRF-Token请求头读取;AJAX 请求必须手动带 header:headers.set('X-CSRF-Token', document.querySelector('meta[name=csrf]').getAttribute('content')) - Gin 的
gin-contrib/csrf默认从_csrf表单字段或X-CSRF-TOKENheader 读,但大小写敏感,别写成X-Csrf-Token - token 有效期默认 24 小时,但若用户长时间停留页面,token 已失效,前端需捕获 403 并重新拉取新 token(比如通过
/api/csrf接口)
静态资源和 API 路径要显式豁免
CSRF 校验不该作用于纯 GET 接口、静态文件、健康检查路径——否则会导致 favicon.ico 403、Swagger UI 加载失败、前端构建产物无法访问。
- gorilla/csrf 提供
csrf.SameSiteLaxMode和csrf.UnsafeSkipCheck,但跳过校验必须靠路径前缀判断,不是靠 method:用csrf.Protect(key, csrf.SkipRequestFunc(func(r *http.Request) bool { return strings.HasPrefix(r.URL.Path, "/static/") })) - Gin 中不要用
r.NoRoute()后补中间件来覆盖 CSRF,而是提前用r.Static("/static", "./assets")注册,它自动绕过所有中间件 - API 接口若混用 GET/POST,务必确认是否真需要 CSRF(如
GET /user/delete?id=123是严重漏洞),不要为省事全跳过
SameSite Cookie 属性不能替代 CSRF Token
设 SameSite=Strict 或 Lax 能缓解部分 CSRF,但不是等价方案。浏览器兼容性、跨子域场景、以及被降级为 GET 的表单提交,都会让 Cookie 策略失效。
立即学习“go语言免费学习笔记(深入)”;
-
Set-Cookie: session=xxx; SameSite=Lax; HttpOnly; Secure对防止从evil.com提交表单有效,但对同站 iframe 内发起的 POST 无效 - 移动端 WebView、某些邮件客户端会忽略 SameSite,而 token 方案仍生效
- Go 标准库
http.SetCookie不自动加 SameSite,必须手动拼字符串或用第三方封装(如golang.org/x/net/http/httpguts判断版本)










