ARTICLE DETAIL

资讯详情

深耕网站建设与运营推广的一线实战洞察。

Go Web 开发中的 session 与 cookie:原理辨析与 net/http 实战(build-web-application-with-golang 第 6.1 节)

Go Web 开发中的 session 与 cookie:原理辨析与 net/http 实战(build-web-application-with-golang 第 6.1 节) 文档教程【免费下载链接】build-web-application-with-golangA golang ebook intro how to build a web with golang项目地址https://gitcode.com/gh_mirrors/bu/build-web-application-with-golang点击查看免费下载HTTP 协议天然无状态如何让服务器识别上一个请求是谁发来的是认证页面抓取、登录态保持与访问统计的共同基础。本篇以开源电子书 build-web-application-with-golang 的 zh/06.1.md 为核心系统讲解 session 与 cookie 的来龙去脉、生命周期分类以及 Go 语言 net/http 包下设置与读取 cookie 的完整实战代码并结合本书 6.2 节的会话管理器设计思路zh/06.2.md说明两者在服务端认证中的配合方式。读完你不仅能准确辨析这两个概念还能直接用 Go 写出可运行的 cookie 读写代码并理解 session 管理器的接口抽象。为什么需要 session 和 cookie一个抓取受限网页的问题先看一个具体场景如何用程序抓取一个访问受限的网页比如新浪微博好友的主页、个人微博页面。通过浏览器我们可以手动输入用户名和密码来访问页面而所谓抓取就是使用程序模拟完成同样的工作因此我们必须先弄清楚登录过程中到底发生了什么。当用户来到微博登录页面输入用户名和密码后点击登录浏览器会将认证信息 POST 给远端的服务器服务器执行验证逻辑。如果验证通过浏览器跳转到登录用户的微博首页。但问题来了登录成功后服务器如何验证我们对其他受限制页面的访问呢因为 HTTP 协议是无状态的服务器不可能知道用户已经在某次 HTTP 请求中通过了验证。最简单的解决方案自然是所有请求都带上用户名和密码但这有两个致命缺陷加重服务器负担每个 request 都需要到数据库验证一次降低用户体验每个页面都需要重新输入用户名密码每个页面都带有登录表单。既然在请求中直接携带用户名与密码不可行就只能在服务器或客户端保存一些可以代表身份的信息于是就有了 cookie 与 session。cookie保存在客户端的历史信息cookie 简而言之就是在本地计算机保存用户操作的历史信息当然也包括登录信息并在用户再次访问该站点时浏览器通过 HTTP 协议将本地 cookie 内容发送给服务器从而完成验证或继续上一步操作。其工作原理可以概括为下图所示的流程服务器通过 Set-Cookie 下发标识浏览器在后续请求中自动携带服务器据此识别客户端。图 6.1 cookie 的原理图cookie 的本质与存储位置Cookie 是由浏览器维持的、存储在客户端的一小段文本信息伴随着用户请求和页面在 Web 服务器和浏览器之间传递。用户每次访问站点时Web 应用程序都可以读取 cookie 中包含的信息。浏览器设置里通常有 cookie 隐私数据选项打开后可以看到很多已访问网站保存的 cookies如下图所示图 6.2 浏览器端保存的 cookie 信息会话 cookie 与持久 cookie生命周期的两种形态cookie 是有时间限制的根据生命期不同分成两种会话 cookiesession cookie和持久 cookiepersistent cookie。会话 cookie不设置过期时间生命周期为从创建到浏览器关闭为止只要关闭浏览器窗口 cookie 就消失了。会话 cookie 一般不保存在硬盘上而是保存在内存里。持久 cookie设置了过期时间例如setMaxAge(60*60*24)浏览器会把 cookie 保存到硬盘上关闭后再次打开浏览器依然有效直到超过设定的过期时间。需要留意的是存储在硬盘上的 cookie 可以在不同的浏览器进程间共享比如两个 IE 窗口而保存在内存的 cookie不同的浏览器有不同的处理方式。session保存在服务器端的会话状态与 cookie 相对session 简而言之就是在服务器上保存用户操作的历史信息。服务器使用 session id 来标识 session这个 id 由服务器负责产生保证随机性与唯一性相当于一个随机密钥避免在握手或传输中暴露用户真实密码。但服务器需要把发送请求的客户端与session对应起来所以仍要借助 cookie 机制获取客户端的标识即 session id也可以通过 GET 方式将 id 提交给服务器。图 6.3 session 的原理图session 一词的语义演变session 中文常翻译为会话本来的含义是指有始有终的一系列动作/消息——比如打电话从拿起电话拨号到挂断电话的整个过程可以称之为一个 session。当 session 一词与网络协议相关联时它往往隐含了面向连接和/或保持状态这样两个含义。在 Web 开发环境下session 的语义又有了新的扩展它指一类用来在客户端与服务器端之间保持状态的解决方案有时候也用来指这种解决方案的存储结构。session 机制的工作流程session 机制是一种服务器端的机制服务器使用一种类似于散列表的结构也可能就是散列表来保存信息。当程序需要为某个客户端的请求创建一个 session 时流程如下服务器首先检查这个客户端的请求里是否包含了一个 session 标识——称为session id如果已经包含 session id说明以前已经为此客户创建过 session服务器就按照 session id 把这个 session 检索出来使用。如果检索不到可能会新建一个这种情况可能出现在服务端已经删除了该用户对应的 session 对象但用户人为地在请求的 URL 后面附加了一个类似 JSESSION 的参数如果客户请求不包含 session id则为此客户创建一个 session同时生成一个与此 session 相关联的 session id这个 session id 将在本次响应中返回给客户端保存。session 机制本身并不复杂然而其实现和配置上的灵活性却使得具体情况复杂多变。这也要求我们不能把某一次的经验、某一个浏览器或服务器的经验当作普遍适用的结论。Go 实战用 net/http 设置 cookieGo 语言中通过net/http包中的SetCookie来设置 cookiehttp.SetCookie(w ResponseWriter, cookie *Cookie)其中w表示需要写入的 responsecookie是一个http.Cookie结构体。它的完整定义如下节选自 Go 标准库 net/http 包type Cookie struct { Name string Value string Path string Domain string Expires time.Time RawExpires string // MaxAge0 means no Max-Age attribute specified. // MaxAge0 means delete cookie now, equivalently Max-Age: 0 // MaxAge0 means Max-Age attribute present and given in seconds MaxAge int Secure bool HttpOnly bool Raw string Unparsed []string // Raw text of unparsed attribute-value pairs }结构体中的注释给出了MaxAge字段三种取值的语义约定这是 Go 社区公认的规则MaxAge 0不指定Max-Age属性即会话 cookie 语义MaxAge 0立即删除 cookie等价于Max-Age: 0MaxAge 0Max-Age属性存在数值以秒为单位。下面是一个完整的设置 cookie 示例——创建一年后过期的 cookie并写入响应expiration : time.Now() expiration expiration.AddDate(1, 0, 0) cookie : http.Cookie{Name: username, Value: astaxie, Expires: expiration} http.SetCookie(w, cookie)这里通过Expires设置了过期时间因此这是一个持久 cookie浏览器会把它保存到硬盘一年内重新打开浏览器依然有效。Go 实战用 request 读取 cookie上面的例子演示了如何设置 cookie 数据接下来演示如何读取 cookie。第一种方式是通过request.Cookie按名称读取单个 cookiecookie, _ : r.Cookie(username) fmt.Fprint(w, cookie)第二种方式是遍历request.Cookies()获取请求中携带的全部 cookiefor _, cookie : range r.Cookies() { fmt.Fprint(w, cookie.Name) }可以看到通过request获取 cookie 非常方便。这两段代码与http.SetCookie配合就构成了服务器下发 cookie → 浏览器自动携带 → 服务器读取的完整闭环——这正是前一节 cookie 原理图的代码级落地。扩展从 cookie 到 session 管理器仓库源码级设计cookie 解决了客户端携带身份标识的问题而 session 将真正的会话数据保存在服务端。本书 zh/06.0.md 开篇即点明了这一章的主线cookie 机制是客户端机制把用户数据保存在客户端session 机制是服务器端机制服务器用类似散列表的结构保存信息每个访客被分配一个唯一的 sessionID它要么通过 URL 传递要么保存在客户端的 cookies 里——你也可以把 Session 保存到数据库这样更安全但效率会有所下降。在此基础上zh/06.2.md 给出了Go 如何实现 session的完整设计。其中最关键的两点与本节内容直接呼应session id 的下发方式正是本节讨论的两种机制一是通过Set-Cookie头把 session 标识符传送到客户端一般将失效时间设为 0即会话 cookie浏览器进程有效二是 URL 重写在返回页面的所有 URL 后面追加 session 标识符。后者在客户端禁用 cookie 时是首选方案。SessionStart 的代码本质就是 cookie 的读写组合。例如 6.2 节中的实现zh/06.2.md先调用r.Cookie(manager.cookieName)读取客户端携带的 session id若不存在则生成新的 id 并通过http.SetCookie写回客户端func (manager *Manager) SessionStart(w http.ResponseWriter, r *http.Request) (session Session) { manager.lock.Lock() defer manager.lock.Unlock() cookie, err : r.Cookie(manager.cookieName) if err ! nil || cookie.Value { sid : manager.sessionId() session, _ manager.provider.SessionInit(sid) cookie : http.Cookie{Name: manager.cookieName, Value: url.QueryEscape(sid), Path: /, HttpOnly: true, MaxAge: int(manager.maxLifeTime)} http.SetCookie(w, cookie) } else { sid, _ : url.QueryUnescape(cookie.Value) session, _ manager.provider.SessionRead(sid) } return }这段代码把本节的所有知识点串了起来cookie 只存放 session id而非用户数据会话数据保存在服务端由 Provider 管理HttpOnly: true用于降低 XSS 窃取 cookie 的风险MaxAge取自管理器配置的maxLifeTime。此外6.2 节还定义了Provider接口SessionInit/SessionRead/SessionDestroy/SessionGC与Session接口Set/Get/Delete/SessionID并设计了全局唯一 session id 的生成方式crypto/rand读取 32 字节后做 base64 编码感兴趣的读者可以直接阅读 zh/06.2.md 完整代码。小结cookie 与 session 的联系与区别session 和 cookie 的目的相同——都是为了克服 HTTP 协议无状态的缺陷但完成的方法不同session通过 cookie 在客户端保存 session id而将用户的其他会话消息保存在服务端的 session 对象中cookie需要将所有信息都保存在客户端。因此cookie 存在一定的安全隐患例如本地 cookie 中保存的用户名密码被破译cookie 被其他网站收集常见途径包括appA 主动设置域 B 的 cookie让域 B 获取 cookieXSS 攻击在 appA 上通过 JavaScript 获取document.cookie并传递给攻击者的 appB。在开始 Web 开发之前有必要将这些基础概念了解清楚才不会在用到时捉襟见肘或是在调 bug 时如无头苍蝇乱转。本章接下来的小节zh/06.2.md、zh/06.3.md 等将详细介绍 session 的 Go 实现、防劫持与各类存储方案本章开篇 zh/06.0.md 提供了完整章节导览全书目录见 zh/preface.md。赞分享文档教程【免费下载链接】build-web-application-with-golangA golang ebook intro how to build a web with golang项目地址https://gitcode.com/gh_mirrors/bu/build-web-application-with-golang点击查看免费下载相关推荐Go Web 开发中的 Session 与 Cookie原理、区别与 net/http 实践Build Web Application with Golang 第 6.1 节Go Web 开发中的 Session 与 Cookie原理、区别与 net/http 实践Build Web Application with Golan文档教程Go Web 开发中的 Cookie 与 Session原理、net/http 实操与安全要点build-web-application-with-golang 第 6.1 节Go Web 开发中的 Cookie 与 Session原理、net/http 实操与安全要点build web application with gola文档教程build-web-application-with-golang 第 6.1 节精读Cookie 与 Session 原理及 Go 实战build web application with golang 第 6.1 节精读Cookie 与 Session 原理及 Go 实战 导读 HTTP 是文档教程创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
返回列表