gin 本身不处理跨域,必须手动加中间件;用 gin-contrib/cors 最省事但配置需谨慎,如 allowcredentials: true 时 alloworigins 不能为 "*",否则浏览器静默拦截;options 预检失败主因是中间件未正确响应或响应头缺失/冲突;关键点包括预检时调用 c.abortwithstatus(204)、access-control-allow-origin 动态回传 origin、所有 cors 头须在 c.next() 前设置;白名单需精确匹配,支持子域名应使用 alloworiginfunc;自写中间件更可控,推荐动态 origin 校验而非硬编码。

直接上结论:Gin 本身不处理跨域,必须手动加中间件;用 gin-contrib/cors 最省事,但配置错一个参数(比如 AllowCredentials: true 时还写 AllowOrigins: ["*"])就会导致前端带 cookie 的请求被浏览器静默拦截——连错误都看不到。
为什么 OPTIONS 预检总失败?
常见现象是:GET 请求能通,POST/PUT 带 JSON 或自定义 Header 就卡在 OPTIONS,控制台报 Response to preflight request doesn't pass access control check。
根本原因是中间件没正确响应预检请求,或响应头顺序/值冲突。关键点:
- 必须在
c.Next()前判断c.Request.Method == "OPTIONS"并调用c.AbortWithStatus(204)(不能用 200) -
Access-Control-Allow-Origin和Access-Control-Allow-Credentials必须同时生效:前者不能是"*",得动态回传请求头里的Origin - 所有 CORS 相关 Header 必须在
c.Next()之前设置,否则预检响应里没有它们
用 gin-contrib/cors 时怎么配白名单域名?
别信“填 ["https://a.com", "https://b.net"] 就完事”这种说法——这个库对 AllowOrigins 是严格字符串匹配,不支持通配符或正则。实际踩坑点:
-
AllowOrigins: []string{"https://admin.example.com"}只放精确域名,不要带路径、尾部斜杠 - 如果前端可能从
http://localhost:3000调试,也得显式加进去,开发环境和生产环境域名要分开配 - 想支持子域名(如
app.example.com和api.example.com),要么全列出来,要么改用AllowOriginFunc动态校验 - 启用
AllowCredentials: true后,AllowOrigins列表里绝对不能出现"*",否则浏览器直接丢弃整个响应
自己写中间件比用库更可控?
是的,尤其当你需要动态 Origin 校验、日志记录或和内部鉴权联动时。最小可用版本核心就三行逻辑:
func CorsMiddleware() gin.HandlerFunc {
return func(c *gin.Context) {
origin := c.Request.Header.Get("Origin")
if origin != "" {
// 白名单校验,例如 strings.HasSuffix(origin, ".example.com")
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,Token")
if c.Request.Method == "OPTIONS" {
c.AbortWithStatus(204)
return
}
c.Next()
}
}
注意:这里没设 Access-Control-Max-Age,因为多数场景下浏览器默认缓存 5 秒已够用;设太长反而会让白名单变更延迟生效。
最易被忽略的是 Origin 校验逻辑本身——很多团队把「允许 localhost 调试」写成 origin == "http://localhost:3000",结果前端换了个端口(比如 Vite 默认 5173)就崩了。真正在意安全的项目,应该用域名后缀匹配或配置驱动,而不是硬编码。
golang免费学习笔记(深入):立即使用
在学习笔记中,你将探索golang的核心概念和高级技巧!











