You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

求助: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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.06 20:55:52