跨域 cookie 失效主因是浏览器丢弃 set-cookie 响应:chrome 80+ 默认 samesite=lax,跨域请求下需同时满足三条件——前端 withcredentials/credentials="include"、后端 access-control-allow-credentials=true 且 origin 精确指定、cookie 显式设 samesite=none 且 secure=true(https 环境)。

为什么跨域 Cookie 总是失效
不是后端没发 Cookie,而是浏览器根本没存——Chrome 80+ 默认把 SameSite 设为 Lax,跨域请求(比如 http://localhost:3000 → http://localhost:8080)下,Set-Cookie 响应头即使返回了,也会被丢弃。你看到的“登录成功但没记住”“每次都要重新鉴权”,大概率卡在这儿。
必须同时满足的三个条件
要让跨域 Cookie 生效,前端、后端、协议三者缺一不可:
- 前端 AJAX 请求必须带
withCredentials: true(axios 是withCredentials: true,fetch 是credentials: "include") - 后端响应头必须设
Access-Control-Allow-Credentials: true,且Access-Control-Allow-Origin不能是"*",得是具体 Origin(如"http://localhost:3000") - Cookie 自身必须显式设置
SameSite=None且Secure=true—— 注意:Secure意味着只能走 HTTPS;本地开发用 HTTP 时,Chrome 会拒绝该 Cookie(Safari/Firefox 更严格)
Go 中设置 Cookie 的关键写法
别用 http.SetCookie() 简单传参,它不支持 SameSite。要用 http.Cookie 结构体手动构造:
使用 uber-go/dig 在 Golang 中实现依赖注入——基于反射容器,提供 Provide/Invoke、dig.In/dig.Out 参数与结果对象,支持命名依赖等
c := &http.Cookie{
Name: "session_id",
Value: "abc123",
Path: "/",
Domain: "localhost", // 注意:跨域时 Domain 不能设为前端域名,通常留空或设为后端主域
MaxAge: 3600,
HttpOnly: true,
Secure: false, // 开发环境用 HTTP 时设 false;生产必须 true
SameSite: http.SameSiteNoneMode, // 必须显式指定
}
http.SetCookie(w, c)
注意:http.SameSiteNoneMode 在 Go 1.15+ 才支持;低于该版本需用整数值 0x03 替代,否则编译失败。
OPTIONS 预检和 CORS 头不能漏
带 Cookie 的跨域请求一定会触发 OPTIONS 预检。如果中间件没处理 OPTIONS 或响应头缺失,请求直接卡死:
-
Access-Control-Allow-Origin必须动态取r.Header.Get("Origin"),不能硬写"*" -
Access-Control-Allow-Credentials必须设为"true",且只在非 OPTIONS 请求中设(OPTIONS 响应里也要设,但重点是 Origin 和 Credentials 匹配) - OPTIONS 请求必须返回
http.StatusOK,且不能执行后续 handler(否则可能重复写 header 或 panic)
最容易被忽略的是:Domain 字段在跨域 Cookie 场景下几乎无用,反而容易因值不匹配导致 Cookie 被拒;真正起作用的是 SameSite + Secure + Credentials 三者的组合校验。










