不能只用 cors.default(),因其硬编码 access-control-allow-origin: "*",而 allowcredentials: true 时浏览器禁止使用通配符,导致生产环境凭据请求被静默拦截。

直接上生产环境前,必须显式配置 CORS;用 cors.Default() 虽快但不安全,尤其在需要携带 Cookie 或指定 Origin 时会失败。
为什么不能只用 cors.Default()
它硬编码了 Access-Control-Allow-Origin: "*",而一旦设置了 AllowCredentials: true(比如要传 Cookie),浏览器就会拒绝该响应——这是硬性限制,不是 Gin 的 bug。另外,* 无法匹配带凭据的请求,开发时看着能通,上线后登录态就丢。
- 本地调试时
http://localhost:3000→http://localhost:8080用*没问题 - 生产环境
https://app.example.com→https://api.example.com必须显式列出域名 -
AllowCredentials: true时,AllowOrigins不能为"*",否则浏览器静默拦截
如何正确配置允许特定源 + 凭据
用自定义 cors.Config 替代默认行为,关键点是 Origin 动态白名单 + 显式开启凭据支持:
config := cors.Config{
AllowOrigins: []string{"http://localhost:3000", "https://app.example.com"},
AllowMethods: []string{"GET", "POST", "PUT", "DELETE", "OPTIONS"},
AllowHeaders: []string{"Content-Type", "Authorization", "X-Requested-With"},
AllowCredentials: true,
MaxAge: 86400,
}
router.Use(cors.New(config))
-
AllowOrigins必须是完整协议+域名+端口,不能写example.com或省略端口 -
AllowHeaders要包含前端实际发送的自定义头,比如Authorization或X-Trace-ID -
MaxAge设为 86400(24 小时)可减少预检 OPTIONS 请求频次
部署时容易忽略的两个硬性条件
CORS 不是单靠后端设置就能跑通的,前后端必须协同满足两个前提:
- 前端 fetch / axios 调用时必须加
credentials: 'include'(或withCredentials: true),否则 Cookie 不会发,后端即使开了AllowCredentials也无意义 - Nginx / 负载均衡层不能覆盖或删除
Access-Control-*响应头,常见于反向代理配置遗漏add_header或未透传 OPTIONS 请求
特别是 Docker 部署时,如果用了 Nginx 作入口网关,务必检查其配置里是否保留了后端返回的 CORS 头——Gin 设置对了,但被 Nginx 吃掉,错误就变得极难定位。











