当前位置:首页 > 文章列表 > Golang > Go教程 > Go 客户端怎么保存 Cookie 并连续请求接口

Go 客户端怎么保存 Cookie 并连续请求接口

来源:17golang原创 2026-09-06 01:40:24 0浏览 收藏

Go 客户端要连续访问登录接口和业务接口,关键是复用同一个 http.Client,并给它配置一个 cookiejar.Jar。登录响应里的 Set-Cookie 会由 Client 自动交给 Jar 保存,下一次请求再按 URL 的匹配规则取回 Cookie;不要把响应头里的整段字符串手动复制到下一个请求。

最小可用组合是:一个逻辑会话对应一个 Jar,一个 Client 持有这个 Jar,所有连续请求都使用这个 Client。Jar 默认在内存中工作,不负责把登录态写入磁盘。
要点速览
  • http.Client.Jar 同时负责接收响应 Cookie 和为后续请求注入匹配 Cookie。
  • Cookie 是否发送由协议、域名、路径、Secure、过期时间等属性共同决定。
  • 多账号或多租户场景不要共用一个 Jar;生产环境建议配置 publicsuffix.List

先把 cookiejar.Jar 绑定到同一个 http.Client

cookiejar.New(nil) 可以创建一个内存 Cookie Jar。将它放进 Client 的 Jar 字段后,Client 会在发出请求前查找匹配 Cookie,并在收到响应后更新 Jar。下面的地址是示例接口,重点在会话对象的连接方式。

package main

import (
    "fmt"
    "io"
    "log"
    "net/http"
    "net/http/cookiejar"
    "net/url"
    "strings"
)

func main() {
    // 一个 Jar 代表一个登录会话,不能在多个账号之间混用。
    jar, err := cookiejar.New(nil)
    if err != nil {
        log.Fatal(err)
    }
    client := &http.Client{Jar: jar}

    // 登录响应如果包含 Set-Cookie,Client 会自动交给 Jar 保存。
    loginBody := strings.NewReader(`{"username":"demo","password":"secret"}`)
    loginReq, err := http.NewRequest(http.MethodPost, "https://api.example.test/login", loginBody)
    if err != nil {
        log.Fatal(err)
    }
    loginReq.Header.Set("Content-Type", "application/json")
    loginResp, err := client.Do(loginReq)
    if err != nil {
        log.Fatal(err)
    }
    io.Copy(io.Discard, loginResp.Body)
    loginResp.Body.Close()

    // 继续使用同一个 Client,业务请求会自动携带可匹配的 Cookie。
    profileResp, err := client.Get("https://api.example.test/profile")
    if err != nil {
        log.Fatal(err)
    }
    defer profileResp.Body.Close()
    fmt.Println(profileResp.Status)

    // Cookies 只用于观察某个 URL 当前能取到哪些 Cookie,不是持久化接口。
    profileURL, _ := url.Parse("https://api.example.test/profile")
    for _, c := range jar.Cookies(profileURL) {
        fmt.Println(c.Name, c.Value)
    }
}

这里的核心不是调用两次 Get,而是始终保留 client 这个会话容器。若每次请求都写成 &http.Client{},或者登录后换了一个没有同一 Jar 的 Client,后续接口自然看不到登录态。

按域名、路径和协议排查 Cookie 为什么没发送

帮助读者把 Cookie 是否可用拆成 URL 与属性之间的静态判断边界。
图2:查看 URL 匹配边界与 Cookie 属性边界,定位 jar.Cookies 为空或业务请求未带 Cookie 的原因。

Jar 不会把所有 Cookie 无条件塞进每个请求。它按照 Cookie 属性和目标 URL 计算“这次能不能带”,因此排查时先把请求 URL 写清楚,再观察 jar.Cookies(u) 的结果。

检查项常见现象处理思路
SchemeCookie 标记了 Secure,但请求使用 HTTP改用 HTTPS,或在测试环境明确区分安全与非安全 Cookie
Domain登录在一个主机,业务请求换了无关域名确认服务端设置的 Domain 与目标主机匹配,不要手动扩大范围
Path同域名不同路径的接口拿不到 Cookie查看 Set-Cookie 的 Path,接口路径不在范围内时不会发送
过期时间第一次请求成功,过一段时间后失效检查 Expires 或 Max-Age,并准备重新登录或刷新会话

jar.Cookies 返回的是指定 URL 当前可用的 Cookie,适合定位“Jar 里有没有”和“这个 URL 能不能拿到”两类问题。它不是把所有内部状态导出的调试快照;如果 URL 不是 HTTP 或 HTTPS,Cookie 列表也会为空。

Go http.Client、cookiejar.Jar、Set-Cookie 与业务请求之间的会话结构关系
图1:查看同一会话中 http.Client 与 cookiejar.Jar 的静态关系,理解 Set-Cookie 如何成为后续请求的可用状态。

为跨子域场景配置 PublicSuffixList

直接传入 nil 作为 Options 对测试很方便,但官方文档明确提示:没有公共后缀列表时,某些域名边界判断会变得不安全。真实服务通常应引入 golang.org/x/net/publicsuffix,让 Jar 能识别 co.uk 这类公共后缀。

# 引入官方 Go 扩展包,让 Cookie Jar 使用公共后缀规则
go get golang.org/x/net/publicsuffix
import (
    "log"
    "net/http"
    "net/http/cookiejar"

    "golang.org/x/net/publicsuffix"
)

func newSessionClient() *http.Client {
    // 公共后缀列表限制 Cookie 的可设置域边界,生产环境不要省略。
    jar, err := cookiejar.New(&cookiejar.Options{
        PublicSuffixList: publicsuffix.List,
    })
    if err != nil {
        log.Fatal(err)
    }
    return &http.Client{Jar: jar}
}

这项配置不会让不同站点共享登录态,作用恰恰是防止服务端越过公共后缀设置过宽的 Cookie。若业务只访问单一主机,它仍然是一个成本很低的安全默认值。

按用户隔离 Jar 并处理内存与并发边界

Client 和符合约定的 CookieJar 可以安全地被多个 goroutine 使用,但“线程安全”不等于“账号隔离”。一个 Jar 里放的是同一逻辑会话的状态;多账号并发时应为每个账号创建独立 Jar 和 Client,避免请求携带错误用户的 Cookie。

另外,cookiejar.Jar 是内存实现,进程重启后登录态不会自动恢复。如果必须跨重启保留会话,需要明确设计持久化 Cookie 的格式、加密和过期清理,并实现自己的 http.CookieJar 或在应用层保存刷新令牌。不要把 Cookie 值直接写入普通日志。

常见问题

为什么登录成功,下一次请求仍然未登录?

最常见原因是换了 Client、没有配置 Jar,或业务 URL 不符合 Cookie 的 Domain、Path、Scheme 与过期条件。先用同一 URL 调用 jar.Cookies 查看匹配结果。

能不能直接复制响应头里的 Set-Cookie?

不建议。手动复制容易带入属性文本、忽略过期和域名规则;让 Client 与 Jar 管理 Cookie 更接近 HTTP 的实际语义。

一个 Cookie Jar 能不能给所有用户共用?

不应该。Jar 可以并发安全地访问,但其中的状态属于会话;多用户服务应按账号、租户或登录上下文隔离。

版本声明
本文转载于:17golang原创 如有侵犯,请联系study_golang@163.com删除
PHP 同一用户的多个请求为什么排队执行PHP 同一用户的多个请求为什么排队执行
上一篇
PHP 同一用户的多个请求为什么排队执行
Java Optional 的 orElse 为什么每次都执行默认方法
下一篇
Java Optional 的 orElse 为什么每次都执行默认方法
查看更多
最新文章
查看更多
课程推荐
  • 前端进阶之JavaScript设计模式
    前端进阶之JavaScript设计模式
    设计模式是开发人员在软件开发过程中面临一般问题时的解决方案,代表了最佳的实践。本课程的主打内容包括JS常见设计模式以及具体应用场景,打造一站式知识长龙服务,适合有JS基础的同学学习。
    543次学习
  • GO语言核心编程课程
    GO语言核心编程课程
    本课程采用真实案例,全面具体可落地,从理论到实践,一步一步将GO核心编程技术、编程思想、底层实现融会贯通,使学习者贴近时代脉搏,做IT互联网时代的弄潮儿。
    516次学习
  • 简单聊聊mysql8与网络通信
    简单聊聊mysql8与网络通信
    如有问题加微信:Le-studyg;在课程中,我们将首先介绍MySQL8的新特性,包括性能优化、安全增强、新数据类型等,帮助学生快速熟悉MySQL8的最新功能。接着,我们将深入解析MySQL的网络通信机制,包括协议、连接管理、数据传输等,让
    500次学习
  • JavaScript正则表达式基础与实战
    JavaScript正则表达式基础与实战
    在任何一门编程语言中,正则表达式,都是一项重要的知识,它提供了高效的字符串匹配与捕获机制,可以极大的简化程序设计。
    487次学习
  • 从零制作响应式网站—Grid布局
    从零制作响应式网站—Grid布局
    本系列教程将展示从零制作一个假想的网络科技公司官网,分为导航,轮播,关于我们,成功案例,服务流程,团队介绍,数据部分,公司动态,底部信息等内容区块。网站整体采用CSSGrid布局,支持响应式,有流畅过渡和展现动画。
    485次学习
查看更多
AI推荐
  • SuperCLUE中文大模型评测基准:功能、能力维度与应用指南
    SuperCLUE
    SuperCLUE是权威的中文大语言模型综合评测基准,涵盖语言理解、知识应用、AI Agent智能体及安全性等12项核心能力。通过多轮对话与客观测试,定期发布榜单与技术报告,为模型研发、优化及行业选型提供科学依据。
    158次使用
  • C-Eval中文评测基准:大语言模型多学科能力评估指南
    C-Eval
    深入了解C-Eval中文评估套件,涵盖52个学科与4级难度。本文详解其功能特点、Zero-shot/Few-shot使用方法及代码示例,助您全面评测LLM中文理解与泛化能力。
    87次使用
  • ClickPrompt:AI提示词生成与优化工具,支持Stable Diffusion、ChatGPT及代码辅助
    ClickPrompt
    ClickPrompt是一款专为AI提示词编写者设计的开源在线工具,支持Stable Diffusion绘图、ChatGPT对话及GitHub Copilot代码辅助。提供Prompt自动生成、一键运行、社区分享及可视化优化功能,帮助用户高效获取精准AI输出。
    46次使用
  • PromptHero官网:AI提示词搜索、优化与学习平台,支持Midjourney/Stable Diffusion
    PromptHero
    PromptHero是专业的AI提示词搜索引擎与优化平台,支持Stable Diffusion、Midjourney等主流模型。提供海量提示词库、分类搜索、在线课程及社区互动,助力用户高效生成高质量AI图像与文本。
    26次使用
  • OpenArt免费开源指南:Stable Diffusion Prompt Book提示词手册详解
    Stable Diffusion Prompt Book
    深入解析OpenArt推出的Stable Diffusion Prompt Book,这本免费的开源提示词指南涵盖从基础语法到高级技巧,提供风格化词库与参数建议,助您优化AI绘画生成效果。
    29次使用
微信登录更方便
  • 密码登录
  • 注册账号
登录即同意 用户协议隐私政策
返回登录
  • 重置密码