Cookie 和 Session 是一个非常有趣的概念, 也是一个老生常谈的话题. 然而, 作者看了许多文章, 也翻看了几本书籍, 它们对 Cookie 和 Session 的概念, 机制的描述都各不一致, 大多文章都只谈到了 Cookie 和 Session 其中之一, 但在现实开发中两者都需要使用. 作者有时候写程序用到了两者但有时候连自己都没理解他们之间的区别, 联系, 机制等等概念.
Cookie
HTTP 的无状态协议是产生 Cookie 技术的重要原因
HTTP 是一种不保存状态, 即无状态 (stateless) 协议. HTTP 协议自身不对请求和响应之间的通信转台进行保存. 也就是说 HTTP 是不会做持久化 (Persistence) 处理的. 当使用 HTTP 进行通信时, 每当有新的请求发送, 就会有对应的新响应产生. 这并不是缺陷, 而是 HTTP 为了更快的处理大量事务.
然而, 无状态协议让业务处理变得困难的情况越来越多了, 如: 我们登录了某宝, 就算我们跳转到了某宝的其他页面, 也需要保持登录这个 "状态", 但 HTTP 协议做不到. 针对这个例子, 网站为了掌握是谁发送的请求, 就需要把用户的状态保存起来.
为了实现期望的保持状态功能, 于是引入了 Cookie 技术, 所以 cookie 的主要作用就是记录状态, 包括会话状态管理, 用户的个性化设置, 浏览器的行为跟踪. 有了 Cookie 再用 HTTP 通信就可以管理状态, 因此就有人说 Cookie 是 HTTP 的扩展.
客户端中的 Cookie
Cookie 是服务器发送到用户浏览器并保存在本地的一小块数据, 它会在浏览器下次向同一服务器再发起请求时被携带并发送到服务器上.
这是我们经常听到的关于 Cookie 的概念, 但从来没见过 Cookie 长什么样子. 在 Chrome 中通过开发者工具可以查看网站用到的所有 Cookie, 以博客园用到的 Cookie 为例.
另外我们可以使用 JavaScript 原生的 API 获取 cookie:document.cookie, 使用该方法获只能获取非 HttpOnly 类型的 cookie.
跟直接在 Chrome 查看 cookie, 使用控制台 Console 得到的结果除了 HttpOnly 以外的 Cookie 都是一样的. 可以发现, 每一个 cookie 都有几个不同的字段: name,value,domain,path,expires/max-age,HttpOnly,secure 来分析一下比较常用的字段:
name 和 value
设置 cookie 的名字和值. 必须设置字段.
domain 和 path
domain 是域名, path 是路径, 两者加起来就是 URL,domain 结合 path 一起来限制 cookie 能被哪些 URL 访问. 概念比较抽象, 举个例子
以博客园为例, 博客园 cookie 的 domain 为 "cnblogs.com",path 为 "/", 若我们请求的 URL 的域名是 "cnblogs.com" 或者它的子域 "home.cnblogs.com", 并且 URL 的路径都是 "/" 或者它的子路径 "/example","/home/user", 以上这些 URL 都能访问 cookie, 浏览器会将这些 cookie 添加到请求的 cookie 头部中去.
以上两个字段是可选的, domain 默认 cookie 所在的域名, path 默认设置该 cookie 的网页所在的目录.
secure
带有此字段的 cookie 表示只有在请求使用 HTTPS 协议的时候才能被传到服务器中. 但通常建议不会把保密的数据放到 cookie 中存储.
HttpOnly
JavaScript 原生 API 能访问浏览器的 cookie, 这可能会遭遇 XSS 攻击, 为了防范, 设置了该字段的 cookie, 原生 API 是无法访问的.
expire 和 Max-age
expires: 表示 cookie 的最长有效时间, cookie 失效时刻 = expires 形式是符合 HTTP-date 规范的时间戳, 这个 Date 是一个通用的首部, 语法: Date: <day-name> <day> <month> <year> <hour>:<minute>:<second> GMT, 可以通过 new Date().toGMTString 获得.
Max-Age: 表示 cookie 存储的最长时间. 单位是秒, 有效期: 创建时刻 + max-age. 跟 expire 的作用的一样的, 若两者都存在则 Max-Age 的优先级高. 该属性在一些老浏览器中不支持.
如果没有给 cookie 设置以上这两个字段, 那么 cookie 默认就是所谓的会话 Cookie, 有效期就是 session, 这里的 session 指的就是会话, 浏览器关闭后 cookie 就没有了整个过程就是一个会话.
HTTP+COOKIE 工作原理
HTTP 是无状态协议, 所以需要 COOKIE 技术来保持状态. 我们知道, Cookie 是服务器发送到用户浏览器并保存在本地的一小块数据, 这里分析一下 HTTP+COOKIE 的工作原理:
考虑两种可能:
1. 客户端第一请求该台服务器, 也就是服务器没有发送 cookie 给该台客户端, 因此客户端的第一次请求是没有 cookie 首部字段数据的, 而服务器作为响应也会将 cookie 首部数据发送到该台客户端中.
2. 客户端不是第一次请求该台服务器, 服务器已经有发送过 cookie 给该台客户端, 那么在客户端上的 cookie 都会随着请求一同发送到服务器中, 而服务器会检查这个 cookie 给你返回相应的数据, 而不再需要设定 cookie.
COOKIE 实践
为了能明白上面的 cookie 工作原理, 以下进行实践, 建议读者跟我一起做
1. 还是以博客园为例, 在账户退出的状态下打开(https://www.cnblogs.com)[博客园首页], 使用 Chrome, 如果对浏览器开发工具比较熟悉也可以使用火狐, 把网站以往的 cookie 清除
2. 进行刷新页面, 再打开 Chrome 开发工具 network, 选择其中的请求, 点击查看
请求首部(Request Header)
以及
响应首部(Response Header)
, 发现响应首部有 set-cookie 字段, 即服务器给浏览器设置的 cookie. 并且, 请求首部是没有 cookie 字段的, 因为我们自己清除了 cookie!
此时, 再去查看 Cookie 面板发现服务器已经给浏览器设置了 Cookie.
再次刷新页面. 自行重复以上步骤, 发现请求首部多了一个 cookie 字段, 即有了 cookie 后, 对服务器的每一次请求都会带上 cookie.
总结
HTTP 的无状态协议是产生 Cookie 技术的重要原因, cookie 是服务器发送到用户浏览器并保存在本地的一小块数据, 它会在浏览器下次向同一服务器再发起请求时被携带并发送到服务器上. cookie 的主要作用就是记录状态, 包括会话状态管理, 用户的个性化设置, 浏览器的行为跟踪.
写到这, 已经涉及不少知识, 文章篇幅太长不好, 第二篇再写 session 以及在 node.JS 的实践. 剧透一下, 通过 Node.JS 操作 cookie 的代码:)
- const express = require('express');
- const cookieParser = require('cookie-parser')
- var server = express();
- server.use(cookieParser('alkdukajvldfq'));
- server.use('/', function(req, res) {
- // 发送 cookie,path 是指定能访问 cookie 的路径, 可从下往上读取, 反则不行, 比如 /=>path:/aaa
- res.cookie('name', 'janro', {path: '/', maxAge: 3600*1000, signed: true});
- // 读取 cookie
- console.log(req.cookies);
- console.log(req.signedCookies);
- // / 和 favicon
- console.log(req.url);
- res.send('OK');
- // 清除 cookie
- res.clearCookie('name');
- });
- server.listen(8080);
下次, session 见.
如果您觉得阅读本文对您有帮助, 请点一下 "推荐" 按钮, 您的 "推荐" 将是我最大的写作动力!
- Reference
- https://segmentfault.com/a/1190000004556040
- https://segmentfault.com/a/1190000007579928
图解 HTTP
JavaScript 高级程序设计
来源: https://www.cnblogs.com/wljqds/p/cookie_session_node.html