CORS 配置与跨域细节

面试问法:前后端分离项目里,GoFrame 的 CORS 怎么配?有哪些细节坑? 一句话结论:用 ghttp.CORSOptions + 路由分组中间件即可:开发期 CORSDefault() 全放行;生产用 AllowDomain 白名单并在放行前用 CORSAllowedOrigin 校验 Origin;携带 Cookie 的请求不能用“通配 * + AllowCredentials”组合,来源必须精确。

要点速览

关注点结论
触发条件浏览器跨域请求由服务端响应头控制
配置载体CORSOptions + r.Response.CORS/CORSDefault/DefaultCORSOptions/CORSAllowedOrigin
预检 OPTIONSServer 按规范自动响应,前提是请求命中带 CORS 头的路由
携带 CookieAllowCredentials + 精确来源,前端还要 withCredentials
生产收敛白名单域名 + 先校验后放行,非法来源直接拒绝,业务不执行

最短示例

// 开发环境:全放行
s.Group("/api", func(group *ghttp.RouterGroup) {
    group.Middleware(func(r *ghttp.Request) {
        r.Response.CORSDefault()
        r.Middleware.Next()
    })
    group.Bind(new(v1.Controller))
})
// 生产:白名单 + 先校验再放行
group.Middleware(func(r *ghttp.Request) {
    opts := r.Response.DefaultCORSOptions()
    opts.AllowDomain = []string{"example.com", "admin.example.com"}
    if !r.Response.CORSAllowedOrigin(opts) { // Origin 不在白名单
        r.Response.WriteStatus(http.StatusForbidden)
        return
    }
    r.Response.CORS(opts)
    r.Middleware.Next()
})

细节与坑

  • 凭证与通配符冲突:Allow-Origin: * 时浏览器禁止携带凭证;白名单场景须把当前 Origin 回显到 Allow-Origin。
  • 中间件顺序:CORS 放最外层且在鉴权之前——否则 OPTIONS 预检被鉴权拦掉,前端表现成“跨域报错”。
  • 请求带 Authorization 时,AllowHeaders 要包含它,否则预检失败。
  • 规范路由(group.Bind)同样适用:中间件挂分组即可,与 OpenAPI 文档可并存。
  • 不要对全站一刀切放开 *,只给需要跨域的 API 分组挂 CORS。

常见追问

  • 追问:本地开发为什么也跨域?——前后端端口不同即跨域;联调常用 dev 代理同源转发或临时全放行。
  • 追问:预检请求每次都发吗?——浏览器按 Access-Control-Max-Age 缓存预检结果,命中缓存就不再发 OPTIONS。

记忆点

  • 公式:中间件 + 分组 + CORSOptions;开发 CORSDefault,生产 AllowDomain + CORSAllowedOrigin 预校验。
  • Cookie 场景记住“凭证不能配通配 *”;字段细节以官方文档为准。
笔记加载中…