根本原因是CORS配置、Cookie属性与客户端凭证未对齐:Beego禁用AllowAllOrigins后需显式指定AllowOrigins,响应头必须设AllowCredentials:true且Origin非通配符;Set-Cookie须带SameSite=None; Secure(HTTPS下),前端fetch/Axios必须设credentials:"include"。

Beego 项目中跨域请求无法携带 Cookie,根本原因不是框架限制,而是 CORS 配置 + Cookie 属性 + 客户端凭证三者未对齐。只要漏掉任一环,document.cookie 看得见、fetch 请求就是不带。
Beego 的 CORS 插件必须禁用 AllowAllOrigins: true
这是最常踩的坑:启用 cors.Allow(&cors.Options{AllowAllOrigins: true}) 后,Beego 会自动设置 Access-Control-Allow-Origin: *,而浏览器明确拒绝在 credentials: 'include' 场景下接受 * 作为源。此时哪怕前端加了 withCredentials: true,响应头也会被浏览器拦截。
正确做法是显式指定允许的源(注意协议、域名、端口全匹配):
beego.InsertFilter("*", beego.BeforeRouter, cors.Allow(&cors.Options{
AllowAllOrigins: false,
AllowOrigins: []string{"https://web.example.com", "http://localhost:3000"},
AllowMethods: []string{"GET", "POST", "PUT", "DELETE", "OPTIONS"},
AllowHeaders: []string{"Content-Type", "X-Xsrftoken", "Authorization"},
ExposeHeaders: []string{"Content-Length"},
AllowCredentials: true, // 必须为 true
}))
-
AllowOrigins不能含通配符,https://*.example.com也不行 - 开发环境若用
http://localhost:3000,生产环境必须换为真实 HTTPS 域名 -
AllowCredentials: true和AllowOrigins必须同时存在,否则无效
后端 Set-Cookie 响应头必须带 SameSite=None; Secure
Chrome 80+ 及后续主流浏览器默认将 SameSite 视为 Lax,跨域请求下若 Cookie 缺少 SameSite=None,浏览器直接拒绝发送。更关键的是:SameSite=None 强制要求搭配 Secure —— 即 Cookie 只能通过 HTTPS 传输。
Beego 中设置 Cookie 时需显式声明:
// 登录成功后设置登录态 Cookie
ctx.SetCookie("session_id", "abc123", 3600, "/", "api.example.com", true, true)
// 参数依次为:name, value, maxAge, path, domain, secure, httpOnly
// 注意第 6 个参数(secure)必须为 true,否则无法满足 SameSite=None 要求
- 本地开发调试 HTTP 环境时,
secure: true会导致 Cookie 不生效 —— 此时只能临时改用SameSite=Lax并确保前后端同域(如都走localhost:8080),或启用 HTTPS 代理 -
domain参数要写一级域名(如"example.com"),子域("api.example.com")才可共享;若留空,浏览器按当前响应 Host 自动设,跨域时往往不匹配 -
httpOnly: true不影响跨域携带,只限制 JS 访问,建议保持开启
前端 fetch / Axios 必须显式开启 credentials
Beego 不干预前端行为,但很多开发者误以为服务端配好就万事大吉。实际上,浏览器默认跨域请求 credentials 为 'omit',必须手动声明:
// Fetch 写法
fetch("https://api.example.com/user", {
method: "GET",
credentials: "include" // 关键:不能是 "same-origin" 或省略
})
// Axios 写法(全局配置)
axios.defaults.withCredentials = true
// 或单次请求
axios.get("/user", { withCredentials: true })
- Vue/React 项目中,若用
createApp或createStore初始化,务必在请求库初始化阶段就设好withCredentials - 如果接口返回 401 且响应头无
Set-Cookie,先检查浏览器 Network → Request Headers 是否含Cookie字段 —— 没有就说明前端没发,不是后端问题 - 表单提交(
<form>)默认携带 Cookie,但 AJAX 必须手动开
Beego 的 XSRF 防御与 Cookie 携带不冲突
Beego 默认启用 XSRF 保护(EnableXSRF = true),它会从请求头(X-Xsrftoken 或 X-Csrftoken)或表单字段(_xsrf)校验 token,但 不会读取或校验 Cookie 中的 XSRF token。也就是说,XSRF token 和登录态 Cookie 是两条独立链路。
如果你把 XSRF token 存在 Cookie 里(比如 Django 风格),Beego 并不支持自动提取 —— 你得手动从 ctx.Request.Header.Get("X-Xsrftoken") 读,或改用表单传参。
- 跨域场景下,XSRF token 应该随业务请求一起放在请求头中,而不是依赖 Cookie 自动携带
- 不要试图用
SameSite=None让 Beego 从 Cookie 读 XSRF token,它压根不这么工作 - 若关闭 XSRF(
EnableXSRF = false),只影响防 CSRF,不影响 Cookie 跨域携带逻辑
真正卡住的地方往往在细节:比如 AllowOrigins 多写了个斜杠、Secure 在 HTTP 下硬开、前端 credentials 拼错成 credential。这些错误不会报 JS 异常,只会静默丢弃 Cookie —— 所以排查时永远先看 Network 面板的 Request Headers 和 Response Headers,而不是翻代码逻辑。


















