
http.Cookie 字段必须显式设置,否则默认不安全
直接 new 一个 http.Cookie 并调用 http.SetCookie,但没填关键字段,等同于裸奔。浏览器收到的 Set-Cookie: session=xxx 没有任何属性,JS 可读、HTTP 可传、跨站可发——XSS 和 CSRF 都能轻松利用。
必须手动设置以下字段:
-
HttpOnly: true:阻止document.cookie读取,防 XSS 窃取 token -
Secure: true:强制仅 HTTPS 传输;开发时若用localhost且无 HTTPS,可临时设false,但上线前必须改回true -
SameSite: http.SameSiteLaxMode:平衡 CSRF 防御与用户体验(Strict会阻断所有跨站 GET,可能影响 OAuth 跳转) -
Path: "/":避免遗漏子路径;若只用于 API,可设为"/api" -
MaxAge: 3600:优先用MaxAge(秒),比Expires更可靠(后者依赖客户端时间)
Value 值必须 URL-safe 编码,且不能存敏感明文
Value 是唯一可能被用户控制的部分,直接拼接用户输入或原始 session token 极易出问题。比如用户昵称含空格或分号,会导致 Cookie 解析失败或截断。
正确做法:
- 用
url.QueryEscape处理所有写入Value的字符串,包括生成的 session token - 绝不在
Value中放user_id、role、email等明文信息 - 若必须存结构化数据,先用
gorilla/securecookie加密+签名,再把结果作为Value - 生产环境推荐只存随机 Session ID,真实数据查 Redis 或数据库
Domain 字段填错会导致 Cookie 根本不发送
Domain 看似可选,但一旦填写就必须匹配请求域名,否则浏览器直接忽略该 Cookie。常见错误是本地开发时填 "localhost" —— 浏览器不支持该值作为 Domain,导致 Cookie 写入失败。
使用规则:
使用 uber-go/dig 在 Golang 中实现依赖注入——基于反射容器,提供 Provide/Invoke、dig.In/dig.Out 参数与结果对象,支持命名依赖等
- 单域名部署(如
example.com):不填Domain,让浏览器自动设为当前 host - 需跨子域共享(如
app.example.com和api.example.com):填"example.com"(注意开头无点) - 本地开发用
127.0.0.1或实际 IP:不要填Domain,或填"127.0.0.1"(部分浏览器支持) - 填了
Domain后,Path和Secure必须同步检查,否则仍可能失效
MaxAge 设为负数 ≠ 删除 Cookie,只是设为会话级
很多人误以为 MaxAge: -1 是“删除”,其实它只是告诉浏览器:“这个 Cookie 是会话 Cookie,关掉浏览器就丢”。要真正删除,必须覆盖写入同名 Cookie 并设 MaxAge: 0 或 Expires: time.Now().Add(-1 * time.Second)。
登出逻辑示例:
cookie := &http.Cookie{
Name: "session_id",
Value: "",
Path: "/",
MaxAge: 0,
HttpOnly: true,
Secure: true,
SameSite: http.SameSiteLaxMode,
}
http.SetCookie(w, cookie)
注意:Value: "" + MaxAge: 0 才是标准清除方式;光清空 Value 不够,旧 Cookie 还在客户端存活。
最易被忽略的是:SameSite=Lax 对 POST 表单提交仍放行,而现代前端常走 JSON API,此时必须配合自定义 header(如 X-Requested-With)校验,或引入独立 CSRF Token。安全不是单点配置,是字段组合 + 服务端验证 + 协议约束的闭环。
golang免费学习笔记(深入):立即使用
在学习笔记中,你将探索golang的核心概念和高级技巧!










