chrome 120+ 跨域请求中 cookie 不发送是因浏览器严格校验三项响应头:set-cookie 必须含 secure 和 samesite=none、access-control-allow-origin 不能为 *、access-control-allow-credentials 必须为 true,任一不满足即静默丢弃。

Chrome 120+ 下,Gin 默认设置的 Cookie 在跨域请求中根本不会被浏览器发送——不是后端没设,是浏览器主动丢弃了。
为什么前端发请求没带 Cookie?
浏览器判断是否发送 Cookie,不看你的 c.SetCookie() 是否执行成功,而是严格检查响应头中的三个关键字段是否同时满足:
-
Set-Cookie必须包含Secure(HTTPS 环境下强制要求)和SameSite=None -
Access-Control-Allow-Origin不能是*,必须是具体 origin(如http://localhost:8080) -
Access-Control-Allow-Credentials必须为true
只要其中任意一项不达标,Chrome 就会静默忽略该 Cookie,Request Headers 里永远看不到 Cookie 字段。
Gin 中正确设置跨域 Cookie 的写法
直接用 c.SetCookie() 很难同时控制 Secure 和 SameSite,推荐改用 http.Cookie 手动构造:
cookie := &http.Cookie{
Name: "session_id",
Value: token,
Path: "/",
Domain: "localhost", // 开发环境用 localhost;生产环境必须填实际域名(不含协议),如 "example.com"
MaxAge: 3600 * 24 * 7,
HttpOnly: true,
Secure: true, // 本地开发若走 HTTP,此处必须设 false,但 Chrome 会拒收 → 所以开发时建议用 HTTPS(如 mkcert)
SameSite: http.SameSiteNoneMode,
}
http.SetCookie(c.Writer, cookie)
注意:Secure: true 和 SameSite: http.SameSiteNoneMode 必须成对出现,否则 Chrome 控制台会报黄色警告,且 Cookie 不生效。
跨域中间件必须同步配对
光设 Cookie 不够,前端请求能带上它的前提是后端明确“允许带凭证”:
- 前端 AJAX(axios/fetch)必须显式开启凭据:
withCredentials: true或credentials: 'include' - Gin 中间件里不能写
c.Header("Access-Control-Allow-Origin", "*"),而要动态取c.Request.Header.Get("Origin") - 必须加
c.Header("Access-Control-Allow-Credentials", "true") - 预检请求(OPTIONS)必须放行,且返回相同 CORS 头
常见错误:把 Access-Control-Allow-Origin 和 Access-Control-Allow-Credentials 分开设置、漏掉 OPTIONS 处理、或在非预检路径上漏设头。
开发环境最常踩的坑
本地调试时,Secure: true + HTTP 协议 = Cookie 被浏览器无视。这不是 Gin 的 bug,是 Chrome 的硬性策略:
- 方案一:用 HTTPS 本地开发(推荐
mkcert生成本地证书) - 方案二:仅开发阶段临时关闭
Secure,但必须同步把SameSite改为http.SameSiteLaxMode或http.SameSiteStrictMode(此时SameSite=None不合法) - 方案三:用
localhost域名 +Domain: "localhost"+Secure: false+SameSite: http.SameSiteLaxMode,可绕过部分限制(但跨域仍需完整 CORS 配置)
真正上线前,Secure 和 SameSite=None 必须回归,且域名必须与前端访问地址完全一致(https://app.example.com ←→ Domain: "example.com")。











