max-age=0是rfc 6265明确定义的即时删除机制,浏览器必须立即将同名cookie标记为过期并从存储中移除;max-age=-1表示会话cookie,仅驻留内存且绑定浏览器进程,不可用于清除。

Cookie过期时间怎么设才真正生效
设置 maxAge 不等于浏览器立刻删除 Cookie,它只告诉浏览器“这个 Cookie 在多少秒后不再发送”。浏览器是否立即清理本地存储、是否在关闭后保留,取决于自身策略(比如 Chrome 会保留过期 Cookie 直到手动清除或重启进程)。
-
maxAge > 0:浏览器按秒倒计时,到期后不再随请求发送;但值仍可能留在开发者工具的 Application → Cookies 列表里(灰色显示为 Expired) -
maxAge == 0:忽略Max-Age字段,退回到依赖Expires时间(Gin 内部不设Expires,所以实际效果等同于会话 Cookie) maxAge (如 <code>-1):等效于删除操作,浏览器收到后会立即移除该 Cookie(无论之前是否过期)
注意:maxAge 单位是秒,不是毫秒,传 3600 是 1 小时,传 3600000 就错成 41 天了。
为什么 localhost 下 secure=true 会导致 Cookie 不生效
当 secure 设为 true 时,浏览器只在 HTTPS 请求中发送该 Cookie。而本地开发用 http://localhost:8080 是 HTTP 协议,此时即使设置了 secure: true,浏览器也会直接忽略该 Cookie —— 不存、不发、也不报错。
- 开发阶段建议设
secure: false,上线后 Nginx 或反向代理启用 HTTPS 后再切为true - 若用自签名证书 + HTTPS 本地调试(如
https://localhost:8080),则secure: true才起作用 - Domain 参数填
"localhost"时,不能带前导点(".localhost"是非法域名,会被静默丢弃)
HttpOnly 和 SameSite 配合才能防 XSS + CSRF
httpOnly: true 只能阻止 JS 读取 Cookie(防 XSS),但它对 CSRF 完全无效;而 SameSite 参数(Gin 的第七个参数)才是控制跨站请求是否携带 Cookie 的关键。
- Gin 的
SetCookie(..., true)第七个参数开启的是SameSite=Lax(不是Strict或None) -
SameSite=Lax允许 GET 表单跳转携带 Cookie(如点击链接访问),但阻止 POST 跨域提交(防大部分 CSRF) - 若需兼容老浏览器(如 IE11),
SameSite不被识别,此时必须靠httpOnly+ 后端校验 Referer/Origin + CSRF Token 组合防御
别以为开了 httpOnly 就万事大吉——没配 SameSite,登录态照样可能被恶意网站发起的 POST 请求盗用。
Domain 和 Path 错配会导致 Cookie 不可见
Cookie 是否出现在某次请求头里,由 Domain 和 Path 共同决定。两者任意一个不匹配,浏览器就过滤掉该 Cookie,后端根本收不到。
-
Domain必须与当前请求域名完全一致,或为子域名通配(如服务部署在api.example.com,想让www.example.com也能读,得设Domain: ".example.com") -
Path是前缀匹配:Path: "/admin"可用于/admin、/admin/user,但不用于/user - 如果路由是
/v1/login但设了Path: "/v2",那这个 Cookie 对该请求完全不可见
最容易被忽略的是:生产环境域名变了,但代码里还硬编码着 "localhost",结果线上用户压根拿不到 Cookie。











