Cookie跨域丢失90%因Access-Control-Allow-Origin与Access-Control-Allow-Credentials冲突:当credentials为true时,Origin不能为"*",必须动态匹配请求头Origin值并严格校验协议、域名、端口;同时需显式处理OPTIONS预检请求返回204并终止链路。

直接说结论:Cookie 跨域丢失,90% 是因为 Access-Control-Allow-Origin 和 Access-Control-Allow-Credentials 配置冲突,而不是 Gin 本身有问题。
为什么 c.Header().Set("Access-Control-Allow-Origin", "*") 会导致 Cookie 不发送
浏览器强制规定:只要响应头中 Access-Control-Allow-Credentials 为 true(即前端设了 credentials: 'include'),Access-Control-Allow-Origin 就不能是 "*"。一旦出现这种组合,浏览器会静默丢弃整个响应——你甚至看不到 Network 面板里的 Response Body,请求状态可能显示为“已取消”或“CORS error”。
常见错误现象:
- GET 请求能拿到数据,POST 或带 body 的请求失败
- Chrome DevTools 显示
Response to preflight request doesn't pass access control check - Application → Cookies 标签页里有值,但 Request Headers 里始终没有
Cookie字段
解决办法只有一条:用请求头中的 Origin 值动态回写,且必须严格匹配协议、域名、端口:
origin := c.Request.Header.Get("Origin")
if origin != "" {
c.Header("Access-Control-Allow-Origin", origin)
c.Header("Access-Control-Allow-Credentials", "true")
}
手写中间件没处理 OPTIONS 导致预检失败
Gin 默认不拦截 OPTIONS 方法,如果中间件没在 Method == "OPTIONS" 时提前返回,请求就会落到后续 handler,而你的业务路由通常没注册 OPTIONS,结果就是 404 —— 浏览器因此拒绝发起真实请求。
关键动作必须做:
- 判断
c.Request.Method == "OPTIONS" - 立即调用
c.AbortWithStatus(204)或c.Status(204),不能调c.Next() - 确保
Access-Control-Allow-Methods包含"OPTIONS",否则预检头校验失败
示例片段:
if c.Request.Method == "OPTIONS" {
c.Header("Access-Control-Allow-Origin", origin)
c.Header("Access-Control-Allow-Credentials", "true")
c.Header("Access-Control-Allow-Methods", "GET,POST,PUT,DELETE,OPTIONS")
c.Header("Access-Control-Allow-Headers", "Content-Type,Authorization")
c.AbortWithStatus(204)
return
}
gin-contrib/cors 配置 AllowCredentials 却仍失效
这个包很省事,但容易踩两个坑:
-
AllowCredentials: true必须和AllowOrigins同时显式配置,只开凭据、AllowOrigins写成["*"],它会自动禁用凭据支持(不是报错,而是静默降级) -
AllowOrigins必须是完整 URL 列表,比如[]string{"http://localhost:3000", "https://app.example.com"},不支持通配子域或协议模糊写法
正确配置示例:
config := cors.Config{
AllowOrigins: []string{"http://localhost:3000", "https://app.example.com"},
AllowCredentials: true,
AllowHeaders: []string{"Content-Type", "Authorization"},
}
router.Use(cors.New(config))
Cookie 本身没设对,跨域再正确也没用
即使 CORS 全对,如果后端 c.SetCookie() 的参数错了,浏览器照样不存、不发。最常错的是这三个字段:
-
domain:开发时填"localhost"是无效的,必须留空或填"127.0.0.1";若用http://localhost:8090访问,domain应为空字符串(浏览器会自动补全) -
secure:本地 HTTP 开发时必须为false;一旦设为true,Chrome 只在 HTTPS 下才发 Cookie -
samesite:设SameSiteNoneMode时,secure必须为true,否则 Chrome 拒绝存储(小黄三角警告)
安全又兼容的本地开发写法:
c.SetCookie("session_id", "abc123", 3600, "/", "", false, true)
这里 domain 为空,由浏览器自动推导;secure 为 false(HTTP 环境下可用);httpOnly 为 true 防 XSS。


















