根本原因是浏览器拒绝发送cookie:access-control-allow-origin设为"*"与allowcredentials:true冲突,w3c规范强制互斥,导致预检失败并丢弃响应。

本地开发时 Axios 配了 withCredentials: true 却不发 Cookie
根本原因是浏览器拒绝发送:Access-Control-Allow-Origin 设为 "*",但后端又开了 AllowCredentials: true。W3C 规范强制要求二者互斥,浏览器直接丢弃响应,前端控制台报错 Response to preflight request doesn't pass access control check: The value of the 'Access-Control-Allow-Origin' header must not be the wildcard '*'。
常见错误操作包括:
- 用
cors.Default()启动中间件 —— 它等价于AllowAllOrigins: true+AllowCredentials: true,开发阶段看着能跑,一加 Cookie 就崩 - 硬编码
AllowOrigins: []string{"*"}并设AllowCredentials: true,结果 OPTIONS 预检通过了,但后续 POST/GET 响应头被浏览器无视 - 前端 URL 是
http://localhost:3000,后端SetCookie时却写了domain: "localhost",Chrome 120+ 会拒绝接受这个组合
前端必须配对的三项设置
只改后端没用,前端 axios 或 fetch 必须显式开启凭证传递,且不能遗漏任一环节:
-
axios.defaults.withCredentials = true(全局)或单个请求加{ withCredentials: true } - 若用
fetch,必须带credentials: "include",写成"same-origin"不行 - 确保请求 URL 的协议、域名、端口与后端
Access-Control-Allow-Origin返回值完全一致 —— 比如后端返回http://localhost:3000,前端就不能用http://127.0.0.1:3000,哪怕它们指向同一服务
Gin 中间件注册顺序和 OPTIONS 处理必须严格
跨域中间件不是“加了就行”,它必须在所有路由注册前调用 r.Use(),否则 OPTIONS 请求可能匹配不到任何 handler,直接 404。
手写最小中间件时,关键三步缺一不可:
- 先取
c.Request.Header.Get("Origin"),为空则跳过(说明不是跨域请求) - 若非
OPTIONS请求,仅设响应头:c.Header("Access-Control-Allow-Origin", origin)、c.Header("Access-Control-Allow-Credentials", "true"),**不能写死"*"** - 遇到
OPTIONS必须立刻终止:if c.Request.Method == "OPTIONS" { c.AbortWithStatus(204); return }—— 用c.Status(204)+c.Next()会导致后续中间件继续执行,可能 panic 或污染响应头
本地调试 Cookie 的 secure 和 domain 设置陷阱
开发环境 HTTP 下,secure: true 的 Cookie 会被浏览器静默丢弃,不报错也不存。这不是 Gin 的问题,是浏览器强制策略。
正确做法:
- 开发时
SetCookie的secure参数设为false,例如:c.SetCookie("session_id", "abc", 3600, "/", "", false, true) -
domain字段留空("")或省略,让 Gin 自动推导为当前 Host;填"localhost"在新版 Chrome/Firefox 中大概率失败 - 登出删除 Cookie 时,
secure和httpOnly必须与设置时一致,否则旧 Cookie 可能残留 —— 开发环境删 Cookie 建议统一用maxAge: -1+ 相同path+ 空domain+secure: false
真正容易被忽略的是:跨域携带 Cookie 不是“连通即生效”,它依赖前端 URL、后端 Origin 响应头、Cookie 的 domain/path/secure 三者严格匹配。少一个条件,浏览器就当它不存在 —— 这种失败没有日志、没有报错,只有 Network 面板里 Request Headers 里看不到 Cookie 字段。











