必须用c.setcookie(),它自动url编码、校验maxage类型、默认启用httponly和secure;禁用手动拼set-cookie或http.setcookie,避免xss与400错误。

直接用 c.SetCookie() 和 c.Cookie() 就够了,别自己拼 Set-Cookie 头,也别调 http.SetCookie() —— 后者漏 URL 编码、类型错、HttpOnly 缺失,三秒内就能引出 XSS 或 400 错误。
怎么安全地设置 Cookie
必须用 c.SetCookie(),它已自动做三件事:值 URL 编码、maxAge 类型校验(只接受 int)、默认加 HttpOnly=true 和安全标志。手写容易翻车:
-
maxAge传time.Second * 3600?Go 会 panic,必须是纯整数秒,比如3600 - 值含中文或空格却不
url.QueryEscape()?浏览器拒收,返回 400 或静默丢弃 -
domain填"localhost:8080"?无效,开发填"localhost",上线必须是"example.com"(不含端口) -
secure = true却走 HTTP?浏览器直接不发该 Cookie,本地调试务必设false
示例:设置一个 1 小时有效期、仅 HTTPS 传输、防 JS 访问的登录标识
c.SetCookie("auth_token", "abc123", 3600, "/", "example.com", true, true)
怎么正确读取和判断 Cookie
c.Cookie("name") 返回的是解码后原始值,不用再 url.QueryUnescape();错误时返回非 nil err,不是空字符串。
- 不要写
if cookie == ""判断是否存在 —— 正确方式是检查err != nil - Cookie 值为
"%E4%BD%A0%E5%A5%BD"(UTF-8 编码)?c.Cookie()已自动解码成"你好" - 想兼容缺失场景?用带默认值的写法:
cookie, _ := c.Cookie("theme"); if cookie == "" { cookie = "light" }
怎么可靠地删除 Cookie
服务器不能“删除”客户端 Cookie,只能覆盖它:同名 + 过期时间设为负数 + 路径/域名/Secure/HttpOnly 与原设置完全一致。
-
maxAge = -1是标准做法,浏览器收到即刻移除 - 路径不匹配?比如原 Cookie 是
path="/admin",删时用了"/"→ 删除失败 - 域名不一致?原设
"example.com",删时填"www.example.com"或空字符串 → 失效 - Secure 标志翻转?原为
true,删时传false→ 浏览器认不出是同一个 Cookie
登出时推荐写法:
c.SetCookie("auth_token", "", -1, "/", "example.com", true, true)
为什么不能用全局 map 模拟 Session 存 Cookie ID
Cookie 只是轻量凭证(比如 session_id=abc123),真正用户数据必须存在服务端 Session 中 —— Gin 本身不提供 Session 支持,gin.Default() 里没有中间件。
- 自己用
map[string]interface{}+sync.Mutex?并发写入直接 panic,或锁粒度错导致数据竞争 - 服务重启?所有 Session 全丢,用户强制登出
- 部署多实例?A 实例生成的 Session ID,B 实例查不到,用户刷新就变未登录
- 正确方案:用
github.com/gin-contrib/sessions+ Redis,redis.NewStore()接收的是*redis.Client,不是地址字符串
Session ID 默认存名为 "session" 的 Cookie,HttpOnly=true 和 Secure=true 生产环境默认开启,改名要前后端同步,否则前端发不过来、后端读不到。











