十分钟轻松看懂Cookie

栏目: 编程工具 · 发布时间: 6年前

内容简介:发现很多地方在介绍cookie的作用时,都喜欢使用购物车的例子,那我们也不妨从这个例子开始说起。场景示例:有用户a和b,都登陆了某个购物网站,此时如果两个用户都点击了【查看购物车】按钮,那么此时服务器就同时收到了2个请求,请求的内容都是:“请告诉我我的购物车有什么商品”。现在问题来了——其实这就是经常看到的那句话

从经典的购物车说起

发现很多地方在介绍cookie的作用时,都喜欢使用购物车的例子,那我们也不妨从这个例子开始说起。

场景示例:有用户a和b,都登陆了某个购物网站,此时如果两个用户都点击了【查看购物车】按钮,那么此时服务器就同时收到了2个请求,请求的内容都是:“请告诉我我的购物车有什么商品”。现在问题来了—— 服务器怎么区分哪个请求对应哪个用户呢

其实这就是经常看到的那句话 http协议是无状态的 。为什么说无状态呢,因为 http 协议可以看成一种简单的应答模式:

  • 客户端发送一个请求,服务端返回相应的内容;
  • 客户端(可能不是同一个客户端了)又再发送一次请求,服务端(服务端还是同一个)就再返回相应的内容,

那么服务端知道两次访问的客户端是不是同一个吗?显然是母鸡呀!

十分钟轻松看懂Cookie

为了解决这个问题,就要介绍今天的主角--Cookie。

cookie登场

可以联想一下生活中。我们如果去一家生意火爆的火锅店吃火锅的场景(我忽然有点想去吃个火锅再回来写了),这时如果有空座了,店员怎么知道在门口等候的顾客应该轮到谁了呢?很简单, 在顾客等候之前,先发个号码牌,后面根据号码辨别身份。

?!!

十分钟轻松看懂Cookie

看到这里,是不是觉得有点饿了?啊呸,是不是觉得灵光乍现,上面说的问题和这个场景不是如出一辙吗?所以,为了能够让 会话 可以被识别,http中也引入了一个号码牌—— cookie 的机制。(会话这个词出现地有点突兀,简单解释下:a用户登录购物网站之后,接下来发生的一系列请求,都应该属于服务端与a的 会话

好了,原理大概说完了,那 cookie 具体怎么实现呢?很简单,放在 http 的头部 (headers) 。在前一篇讲状态码时,已经稍稍涉猎了一点 http 头部的相关知识,简单的来说 http 的头部是一个js对象,里面存放了一系列的键值对(key:value)用来表示各种信息, http的【请求】和【响应】都有头部 ,而cookie机制的实现,则是借助了其中的两个字段: CookieSet-Cookie ,整个运行流程可以分成以下步骤:

  1. 客户端发送一个 http 请求到服务端(我去告诉店员,我要吃火锅了)
  2. 服务端响应该请求,并且在响应头中包含了 Set-Cookie (店员回应我,并且给了我一张号码牌,告诉我有任何需要都带着号码牌来申请)
  3. 客户端发送请求,请求头包含字段 Cookie (我到店里后,呼叫服务员来一份雪花牛肉,并且告诉他, 我的号码牌是6号
  4. 服务端根据请求中 Cookie 的内容响应。(服务员听到后,根据我的号码牌,给我给上了对应的菜)

在上述过程中,可能同时也有其他号码牌的顾客在与服务员进行类似的交流过程,由于 服务员发给每个顾客的号码牌上的数字都是唯一的 ,所以不必害怕弄混。

cookie 的基本原理就是这么简单!

十分钟轻松看懂Cookie

当然,在生活中吃完饭我们就把号码牌丢掉了,下次来吃重新取号就行;但是在http请求中,cookie可以设置使用期限,比如说6个月后才过期。那么客户端接到这个内容后,就会把cookie缓存报本地的某个位置,之后如果访问相同的站点,就可以直接取出对应的cookie来使用。接下来我们看个实际案例(又到了紧张刺激的举例子环节,这次不仅有例子,还有精美配图,我觉得可以点个赞再走~)。

首先,我们打开chrome浏览器的【设置】-【内容设置】-【cookie】(也可以在设置的顶部直接搜索),进入后可以查看【所有的cookie和网站数据】,看看segmengt这一条数据。里面一共有7个cookie,展开看详细内容,可以看到 域名脚本可访问到期时间 等属性,

十分钟轻松看懂Cookie 十分钟轻松看懂Cookie

这些属性后面再介绍,为了看到整个流程,我们先清除这个站点下的 cookie ,当然也可以直接ctrl+shift+n打开一个隐身模式来直接测试。(隐身模式不会记录cookie,咳咳,我当然也是为了学习写代码才发现这个功能的!)

然后我们打开 segment 站点,同时打开f12调试 工具 的network面板。可以看到这个请求(可以直接选 doc 类型查看,或者搜索框里搜 segment.com 快速过滤),

十分钟轻松看懂Cookie

可以看到这就对面前面说的第一个步骤:客户端发送请求,服务端响应并提供 set-cookie (也就是发放号码牌的步骤)。

接下来我们登录这个网站并且再次请求这个站点。此时 响应头 里已经不再有供 set-cookie 字段,因为cookie已经被缓存了(可以去前面的设置里再看看),而 请求头 里多了一个 cookie 字段。(这就是使用号码牌的步骤了)。

接下来我们把面板的请求类型切换到 xhr ,再 点点页面上的功能,比如收藏本文,或者给作者点赞、打赏(疯狂暗示) 等等。 可以看到请求里都带上了 cookie 这个头部。

十分钟轻松看懂Cookie

直到cookie过期,或者下次我们又手动删除这个站点cookie之前,原有的cookie都可以继续使用。

set-cookie和cookie

接下来我们来说说set-cookie和cookie字段的具体内容。按照流程首先是来自服务端的 set-cookie ,直接copy一个前文的cookie下来,依此介绍:

set-cookie: test_cookie=CheckForPermission; expires=Mon, 25-Feb-2019 00:28:09 GMT; path=/; domain=.doubleclick.net
  1. 首先 test_cookie=CheckForPermission ,表示这个cookie的键值对,每个cookie都会有自己的名称和值
  2. expires=Mon, 25-Feb-2019 00:28:09 GMT 表示cookie的有效期,这个值如果不指定,那么默认值为 到浏览器关闭之前为止
  3. path=/ ,将服务器上的某个文件目录作为cookie的使用对象(这么抽象的解释肯定是书上说的),简单的来说,是指定服务端 有权限访 问Cookie的路径,例如/session/,表示只有/session/下才可以访问cookie ,默认为文档所在的目录。
  4. domain=.doubleclick.net ,表示cookie所在的域。默认为创建cookie的域。也就是请求地址,比如前面的 segment.com
  5. secure ,这个属性前面没有,表示只在https安全通信时才发送cookie
  6. httpOnly ,这个属性前面也没有,是用来限制使用脚本访问cookie的,设置了这个值后,无法在浏览器客户端使用 jsdocument.cookie 读取Cookie内容(页面内部是可以访问的),这个功能可以用来防止xss攻击中利用js劫持cookie。

而cookie字段就简单的多:同样看一个实例:

cookie:HPSESSID=web2~a667ecfoft7u5e3umvgam3vs65; Hm_lvt_e23800c454aa573c0ccb16b52665ac26=1551052787; _ga=GA1.2.113018985.1551052787; _gid=GA1.2.1438865670.1551052787;

直接以键值对的形式发送需要的cookie,使用分号分割表示多个cookie。

使用cookie时,服务端会对发送来的cookie进行校验,校验的内容为 过期时间(expire)、域(domain)、路径(path)、协议(是否secure) ,从而判断cookie是否有效。如果服务端已经发出了一个cookie,之后想修改cookie的值怎么办呢?那就要创建一个 同名 的cookie进行覆盖删除。 同名的要求是除了name和expire以外的属性要和原来的cookie一致 ,否则会被当作不同的cookie保存。

cookie的优缺点

从前面的介绍我们至少可以看出cookie至少有以下几个优点:

  1. cookie的内容保存在客户端,不占用服务器资源
  2. 有效时间可配置,使用灵活
  3. 简单的键值对结构,较为轻量

当然缺点也显而易见:

  1. cookie的长度一般会被限制在4k左右,超出部分会被丢弃
  2. 浏览器可存储的cookie数量一般也是有数量限制的,ie8、Firefox限制为每个域名50个,chrome没有限制,但是由于规则1的存在,一个域名下cookie肯定也不能非常多,否则内容就超过4k了
  3. cookie功能可以被禁用,这就意味着基于cookie开发的功能要考虑如何应该这种情况
  4. 不安全,容易被截取并篡改。
  5. 某些数据必须存在服务端,比如下面即将介绍的跨设备数据同步。

cookie的使用场景

大部分讲cookie的文章都会提到这两个例子,但是很少有具体的说明大概是怎么实现的。这里做下简单的介绍。

自动登录

假设某网站登录时,提供了一个可以勾选的【7天内免登录】复选框,用户勾选并正确登录之后的流程大概是这样的:

  1. 客户端发送请求到服务端,请求信息里包含用户名密码(当然一般是加密过的,但是我发现segment这里登录的时候居然直接把密码明文放在post的data里,应该提个改进类的bug过去给他-_-!)
  2. 服务端接收请求后, 创建一个id比如111,用于表示当前发送请求的客户端,并存在服务端的某个位置 ,简单点可以认为就存在一个名叫 sessions 的数组里面吧。之后,把这个id放在响应的set-cookie里面返回。例如:

    set-cookie:sessonId=111

同时,服务端设定数组sessions中的保存的111在7天后删除

  1. 客户端收到这个cookie之后保存,之后再次访问的时候都带上这个cookie,服务端接收到cookie里附带的sessionId=111后,去 sessions 数组查询是否含有111,

    • 如果发现有,说明当前用户可以自动登录,可以直接跳转到登录之后的页面
    • 如果不存在(已经被自动删除了),那么说明要重新登录

(其实在上面已经悄咪咪的说了一丢丢session的内容,但是本着每次着重说明一个知识点、尽量剥离无关内容的原则,依然不在本文插入session的相关知识)

未登录时的购物车

本文已经多次提到购物车了,但是细心的朋友可以看到,这里的前面添加了“未登录”,那登录时候为什么不用呢?因为我们前面比较优缺点的时候,有提到cookie毕竟只能存储在发送请求的那个客户端设备,而电商网站一般是允许 多终端 登录的(x宝,x猫,x夕夕等),如果使用cookie来保存登录后的购物车内容,那更换设备的时候就无法查到了,所以登录状态下的购物车一般是存到数据库中的,只在离线的时候使用cookie的方式来处理比较合适。

核心思路:

  1. 首先初次进入页面时,客户端发送get请求,服务端在响应的set-cookie返回给客户端一个 商品列表
  2. 用户点击【将某商品添加到购物车】,客户端发送请求携带cookie发送请求,并且 在请求体中携带商品id
  3. 服务端接受到请求后,从 请求头的cookie 中取出商品列表,从 请求体中 取出本次商品id,然后查找商品列表是否包含该商品id,如果包含,那对应商品id增加;如果不存在,则从数据库查找该商品,并添加该商品信息和数量,并更新到cookie中

如何读写cookie

js读写cookie的方法到处都有,随便搜索下应该就能找到,本文还是着重于说明cookie的原理,就不在此赘述了。

十分钟轻松看懂Cookie

小结

本文对cookie的原理和应用场景进行了说明,依然延续以往的“一篇文章只说一件事”的习惯(程序员的事,怎么能叫偷懒呢,这叫模块化封装)。希望能对看完的同学有所帮助(就算是只收获了表情包也是极好的)。顺便说一下,前一篇文章似乎效果不错,骗到了很多收藏和点赞,非常开心( 再次疯狂暗示

惯例:如果内容有错误的地方欢迎指出(觉得看着不理解不舒服想吐槽也完全没问题);如果有帮助,欢迎点赞和收藏,转载请征得同意后著明出处,如果有问题也欢迎私信交流,主页有邮箱地址


以上就是本文的全部内容,希望本文的内容对大家的学习或者工作能带来一定的帮助,也希望大家多多支持 码农网

查看所有标签

猜你喜欢:

本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们

The Linux Command Line

The Linux Command Line

William E. Shotts Jr. / No Starch Press, Incorporated / 2012-1-17 / USD 39.95

You've experienced the shiny, point-and-click surface of your Linux computer-now dive below and explore its depths with the power of the command line. The Linux Command Line takes you from your very ......一起来看看 《The Linux Command Line》 这本书的介绍吧!

CSS 压缩/解压工具
CSS 压缩/解压工具

在线压缩/解压 CSS 代码

RGB转16进制工具
RGB转16进制工具

RGB HEX 互转工具

Base64 编码/解码
Base64 编码/解码

Base64 编码/解码