必须用 c.Cookie() 和 c.SetCookie() 操作 Cookie,手动设置易漏 HttpOnly 导致 XSS;Session 需用 gin-contrib/sessions,避免内存模拟缺陷;Cookie 存轻量标志,Session 存敏感数据,二者协同使用更安全。

Cookie 读写必须用 c.Cookie() 和 c.SetCookie()
直接操作 HTTP 头或自己拼 Set-Cookie 字符串会出问题:Gin 的 c.SetCookie() 内部做了 URL 编码、Secure/HttpOnly 标志处理、过期时间标准化,手动设置容易漏掉 HttpOnly=true 导致 XSS 风险,或传错 maxAge 类型(必须是 int,不是字符串或 time.Duration)。
读取时 c.Cookie("name") 返回的是解码后的原始值;如果 Cookie 值含特殊字符(如空格、中文),服务端写入时已自动编码,读取时无需再 url.QueryUnescape —— Gin 已帮你做完。
-
maxAge = -1表示立即删除 Cookie(浏览器收到后清空) -
maxAge = 0表示忽略 Max-Age 字段,退化为会话级 Cookie(关浏览器即失效) - 开发时
domain设为"localhost";上线必须改成实际域名,且不能带端口("example.com:8080"无效) -
secure = true时,HTTP 请求无法携带该 Cookie,只在 HTTPS 下生效 —— 本地调试若没配 HTTPS,务必设为false
Session 不是 Gin 内置功能,必须用 gin-contrib/sessions
Gin 本身不提供 Session 管理,gin.Default() 里没有 Session 中间件。强行自己用 map + mutex 模拟内存 Session,会遇到并发读写 panic、重启丢失、多实例不共享三大硬伤。
标准做法是引入 github.com/gin-contrib/sessions,它封装了存储后端抽象,支持内存、Redis、PostgreSQL 等。最常用的是 Redis 方案:
- 初始化时需传入 Redis 客户端(
redis.NewStore(…)),不是字符串地址 - Session key 名默认是
session,可通过sessions.NewCookieStore(…).Options(sessions.Options{…})修改,但改完前后端必须一致 - 调用
session.Get("user_id")返回的是interface{},需要类型断言,比如v, ok := session.Get("user_id").(int64) - 修改 Session 后必须显式调用
session.Save(),否则变更不会写入后端 —— 这点极易遗漏,导致“存了但下次读不到”
Session ID 存在哪?默认走 Cookie,别试图改存储位置
Session ID 总是通过 Cookie 传递,这是 HTTP 协议约束决定的。你不能把 Session ID 放 query string 或 header 里替代 Cookie —— 除非自己重写整个 Session 中间件(代价远高于收益)。
创建全面的交接文档,使新AI代理能够无缝继续工作,消除歧义。解决上下文耗尽问题。 时机:(1)用户请求保存交接,(2)上下文即将满,(3)主要任务完成,(4)会话结束,(5)恢复工作时。 关键词:保存状态、创建交接、上下文已满、暂停、从...恢复、加载交接、保存进度、会话转移、交接
gin-contrib/sessions 默认使用名为 session 的 Cookie 存储 ID,并自动设置 HttpOnly=true、Secure=true(生产环境)、SameSite=Lax。这些安全选项不能关闭,否则可能被 CSRF 或 XSS 利用。
- 前端 JS 无法读取该 Cookie(
HttpOnly生效),所以登录态对前端透明,只能靠接口返回状态判断 - 跨域请求时,若前端发
credentials: 'include',后端必须设置c.Header("Access-Control-Allow-Origin", "https://your-frontend.com"),不能用* - Cookie 的
Path默认是"/",确保所有路由都能携带;改窄了(比如"/api")会导致登录页(/login)无法写入 Session
Cookie 和 Session 混用时的典型陷阱
常见错误是把用户敏感数据(如密码哈希、token)直接塞进 Cookie,或把 Session 当长期存储用。两者定位完全不同:Cookie 是客户端轻量凭证载体,Session 是服务端有状态会话容器。
- Cookie 值不要超过 4KB,否则部分浏览器截断;Session 数据无此限制(取决于后端存储)
- 用 Cookie 存 “是否已登录” 标志(如
logged_in=true)+ Session 存用户 ID,比只用 Cookie 更安全 —— 前者可快速拒绝未登录请求,后者防伪造 - Session 过期时间由后端控制(Redis TTL 或内存定时清理),Cookie 的
maxAge只影响客户端何时删掉 Session ID,两者要对齐,否则出现“Cookie 没过期但 Session 已销毁” - 调用
c.Redirect()后,若没在重定向前session.Save(),新页面将读不到刚写入的 Session —— 因为重定向响应发出后,中间件链已终止
Session ID 的生成、校验、续期逻辑全由中间件托管,别在 handler 里手动解析 Cookie 或查 Redis —— 违反抽象层,后续换存储方案就得重写业务代码。








