echo 默认不防 csrf,需手动集成 csrf.new() 中间件并确保 session 已启用;表单须含 _csrf 隐藏字段,ajax 需传 x-csrf-token 头且 credentials: 'include';还需配置 samesite、httponly、secure 及安全响应头。

echo.New() 启动的服务默认不防 CSRF,必须手动加中间件
刚用 echo.New() 起服务时,所有表单提交都裸奔——攻击者只要诱导用户访问恶意页面,就能用其 Cookie 提交转账、删账号等请求。Echo 不像 Django 那样开箱即防,它只做路由分发,CSRF 校验得你亲手补。
关键动作只有三步:
- 执行
go get github.com/labstack/echo-contrib/csrf安装包 - 在
e := echo.New()之后、任何e.GET()或e.POST()之前,调用e.Use(csrf.New()) - 确保 session 已启用(比如用
github.com/gorilla/sessions),否则csrf.New()拿不到会话上下文,Token 始终为空
漏掉任一环,csrf.Token(c.Request()) 就返回空字符串,表单一提交直接 403。
HTML 表单里必须写 <input type="hidden" name="_csrf" value="{{.CSRFToken}}">
Token 不是自动注入 DOM 的,Echo 中间件只认固定字段名 _csrf 和固定位置:POST body 里的 form 字段(不是 query string,也不是 header)。如果你用 AJAX 提交,得手动把 Token 放进 X-CSRF-Token 请求头,且前端 fetch 必须设 credentials: 'include',否则 Cookie 不带,Session 找不到,校验直接失败。
常见翻车点:
Go 配置库,使用 spf13/viper — 分层优先级(flag > env >file > KV > default),提供 BindPFlag/BindPFlags、SetEnvPrefix + SetEnvKeyReplace 等功能。
- 模板里写错变量名,比如
{{.CsrfToken}}或{{.token}}→ 中间件收不到值 - 用
text/template渲染但没传.CSRFToken上下文 → 隐藏字段 value 为空 - 表单 method 写成 GET → 中间件默认不校验 GET 请求(可配,但不推荐)
CSRF 中间件 403 时别急着关,先查 Token 传输链是否断裂
页面能打开、Token 看起来也渲染出来了,但一提交就 403,大概率是 Token 从服务端生成到客户端提交之间断了哪一环。
排查顺序建议:
- 在 handler 里加
log.Printf("token: %s, cookie: %v", csrf.Token(c.Request()), c.Request().Cookie("sessionid")),确认 Token 非空、Cookie 存在 - 浏览器开发者工具 Network 标签页,点提交请求 → 查看 Request Payload 是否含
_csrf=xxx字段;Headers 里是否有Cookie: sessionid=... - 检查中间件顺序:
e.Use(csrf.New())必须在e.Use(session.Middleware(...))之后,否则 session 尚未加载,CSRF 拿不到会话 ID - 本地开发用 HTTP 时,确保
csrf.New()未启用SecureOnly(true)(它会拒绝非 HTTPS 的 Cookie 读取)
光有 CSRF Token 不够,还得配 SameSite Cookie 和安全响应头
CSRF Token 是核心,但它只是第一道锁。如果 Cookie 被第三方站点携带,Token 再严也白搭。所以必须强制设置 SameSite=Lax(或 Strict)并搭配 HttpOnly、Secure(HTTPS 下)标志。
同时,这几个响应头不能少:
-
X-Content-Type-Options: nosniff—— 防止浏览器 MIME 类型嗅探后执行恶意 JS -
X-Frame-Options: DENY—— 防点击劫持,避免你的登录页被套进 iframe -
Content-Security-Policy: default-src 'self'—— 限制脚本、样式等资源只从同源加载,XSS 利用难度陡增
这些头得统一加在中间件里,比如 e.Use(middleware.Secure())(Echo 自带)或自己写个简单中间件,千万别只在某个 handler 里塞——漏一个接口,整条防线就可能被绕过。
golang免费学习笔记(深入):立即使用
在学习笔记中,你将探索golang的核心概念和高级技巧!










