gin默认不处理跨域因是轻量框架,手动中间件若注册顺序错或提前写响应头会导致options预检失败;正确做法是中间件置于路由注册前、c.next()后统一设头,且alloworigins不可含*(当allowcredentials为true时)。

为什么 Gin 默认不处理跨域,而加个中间件就报错?
因为 Gin 是轻量框架,不内置 CORS 行为;你手动写的中间件如果没按顺序注册、或在 c.Next() 前就写了响应头,浏览器会直接拒绝预检请求(OPTIONS)。常见现象是:前端发 POST 请求时控制台报 Response to preflight request doesn't pass access control check,但 GET 却正常。
正确做法是让中间件在 c.Next() 之后统一写响应头,并确保它在所有路由注册前被 Use():
- 必须放在
r := gin.Default()后、任何r.GET/POST前调用r.Use(corsMiddleware) - 中间件内部不能提前
c.Abort()或c.JSON(),否则OPTIONS预检无法返回 204 - 若用了
gin-contrib/cors,注意其Config中的AllowOrigins必须显式指定域名,["*"]在带凭证(credentials)时无效
gin-contrib/cors 怎么配才能只允许多个指定域名?
别直接写 ["https://a.com", "https://b.net"] 就完事——这个库默认把 * 当作通配符,但实际匹配逻辑是「完全相等」或「前缀匹配」,且不支持正则。如果你填了 ["https://*.example.com"],它不会生效。
实操建议:
- 用完整域名列表,如
[]string{"https://admin.example.com", "https://app.example.com"} - 如果需要动态判断(比如从请求头取
Origin再白名单校验),别用gin-contrib/cors,自己写中间件更可控 - 配置
AllowCredentials: true时,AllowOrigins不能含"*",否则浏览器直接拒收响应头 - 示例片段:
config := cors.Config{<br> AllowOrigins: []string{"https://a.com", "https://b.com"},<br> AllowMethods: []string{"GET", "POST", "PUT", "DELETE", "OPTIONS"},<br> AllowHeaders: []string{"Content-Type", "Authorization", "X-Requested-With"},<br> AllowCredentials: true,<br>}
自己写一个最小可用的 CORS 中间件要注意什么?
核心就三件事:响应预检请求、设置响应头、放行后续处理。容易踩的坑是漏掉 OPTIONS 处理,或把 Access-Control-Allow-Origin 写死成 * 导致带 cookie 的请求失败。
使用 uber-go/dig 在 Golang 中实现依赖注入——基于反射容器,提供 Provide/Invoke、dig.In/dig.Out 参数与结果对象,支持命名依赖等
关键点:
- 先检查
c.Request.Method == "OPTIONS",如果是,立刻c.Status(204)并c.Abort(),不走后续逻辑 - 从
c.Request.Header.Get("Origin")取值,再比对白名单(注意协议、端口、路径都要一致) - 只在匹配成功时才写
c.Header("Access-Control-Allow-Origin", origin),否则不写该头——避免暴露无效策略 - 必须显式写
c.Header("Access-Control-Allow-Credentials", "true")才能让前端发带withCredentials的请求
前端带 Authorization 头时后端为什么收不到?
不是后端没收到,而是浏览器根本没发出去——因为 Authorization 不在简单请求头范围内,触发预检后,如果后端没在 Access-Control-Allow-Headers 里声明它,浏览器就拦截了整个请求。
解决方式很直接:
- 确保
AllowHeaders列表包含"Authorization"(大小写敏感,"authorization"无效) - 如果还用了自定义头(如
X-Trace-ID),也得一并加进去,缺一个都不行 - 注意
gin-contrib/cors默认的AllowHeaders是空的,不显式配置就会丢掉所有非简单头 - 验证方法:用
curl -H "Origin: https://a.com" -I http://localhost:8080/api看响应头是否含Access-Control-Allow-Headers: Authorization
跨域真正麻烦的从来不是代码几行,而是浏览器那套严格但隐晦的预检规则——每次加新头、换域名、开凭证,都得重新过一遍 OPTIONS 流程。别信“配个中间件就完事”,多抓包看预检响应头,比查文档快得多。
golang免费学习笔记(深入):立即使用
在学习笔记中,你将探索golang的核心概念和高级技巧!










