求助:Golang后端发送的Cookie无法被浏览器保存
问题描述
基于Golang的net/http包开发API,搭配JS前端实现登录时设置Cookie,预期Cookie会被携带到其他接口。该功能在Postman中正常,但浏览器中Cookie既不保存也不携带到后续请求。
后端SetCookie代码
func SetCookie(w *http.ResponseWriter, email string) string { val := uuid.NewString() http.SetCookie(*w, &http.Cookie{ Name: "goCookie", Value: val, Path: "/", }) return val }
前端请求代码
async function getDataWithQuery(query, schema){ let raw = `{"query":"${query}", "schema":"${schema}"}`; let requestOptions = { method: 'POST', body: raw, redirect: 'follow', }; try{ let dataJson = await fetch("http://localhost:8080/query/", requestOptions) data = await dataJson.json(); }catch(error){ console.log(error); } return data; }
已尝试设置Cookie的SameSite属性、前端添加credentials:"include",但均无效。
解决方案
1. 完善Cookie的关键属性设置
浏览器对Cookie的安全性校验比Postman严格,必须明确配置核心属性:
func SetCookie(w http.ResponseWriter, email string) string { // 移除w的指针,http.SetCookie接收原生ResponseWriter即可 val := uuid.NewString() http.SetCookie(w, &http.Cookie{ Name: "goCookie", Value: val, Path: "/", HttpOnly: true, // 防XSS攻击,同时让浏览器正确识别并保存Cookie Secure: false, // 本地HTTP开发用false,上线后改为true(仅HTTPS环境生效) SameSite: http.SameSiteLaxMode, // 跨域场景改用SameSiteNoneMode,需配合Secure: true MaxAge: 86400, // 设置24小时有效期,避免会话Cookie关闭浏览器即失效 Domain: "localhost", // 明确绑定域名,本地开发填localhost }) return val }
注意:若前端与后端端口不同(如前端在3000、后端在8080),需将
SameSite设为SameSiteNoneMode,同时Secure设为true。本地HTTP环境下可在Chrome中开启chrome://flags/#unsafely-treat-insecure-origin-as-secure,将后端地址加入列表,允许不安全环境下使用Secure Cookie。
2. 前端请求强制携带凭证
确保所有接口请求都添加credentials: "include",同时明确请求头格式:
async function getDataWithQuery(query, schema){ let raw = JSON.stringify({ query, schema }); // 改用JSON.stringify避免字符串拼接漏洞 let requestOptions = { method: 'POST', body: raw, redirect: 'follow', credentials: 'include', // 强制携带Cookie headers: { 'Content-Type': 'application/json', // 明确Content-Type,后端才能正确解析请求体 } }; try{ let dataJson = await fetch("http://localhost:8080/query/", requestOptions) data = await dataJson.json(); }catch(error){ console.log(error); } return data; }
3. 后端配置跨域(CORS)中间件
若前端与后端不在同一端口/域名,必须添加CORS中间件允许携带凭证:
func corsMiddleware(next http.Handler) http.Handler { return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { origin := r.Header.Get("Origin") w.Header().Set("Access-Control-Allow-Origin", origin) // 允许请求来源,不能用*配合AllowCredentials w.Header().Set("Access-Control-Allow-Methods", "GET, POST, PUT, DELETE, OPTIONS") w.Header().Set("Access-Control-Allow-Headers", "Content-Type") w.Header().Set("Access-Control-Allow-Credentials", "true") // 核心配置,允许携带Cookie if r.Method == "OPTIONS" { w.WriteHeader(http.StatusOK) return } next.ServeHTTP(w, r) }) }
将中间件注册到路由:
http.Handle("/query/", corsMiddleware(http.HandlerFunc(queryHandler)))
4. 浏览器端排查
- 打开F12开发者工具,切换到
Application标签,查看Cookies下的localhost是否存在goCookie; - 在
Network标签中查看登录请求的Response Headers,确认Set-Cookie头是否正确返回; - 检查是否有广告拦截类插件阻止了Cookie存储。
内容的提问来源于stack exchange,提问作者Mohamed Yasser
相关产品推荐
相关产品推荐

