深刻浅出谈Cookie

从经典的购物车提及

发现不少地方在介绍cookie的做用时,都喜欢使用购物车的例子,那咱们也不妨从这个例子开始提及。程序员

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

其实这就是常常看到的那句话http协议是无状态的。为何说无状态呢,由于http协议能够当作一种简单的应答模式:chrome

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

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

http的无状态

为了解决这个问题,就要介绍今天的主角--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,固然也能够直接ctrl+shift+n打开一个隐身模式来直接测试。(隐身模式不会记录cookie,咳咳,我固然也是为了学习写代码才发现这个功能的!)

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

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

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

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

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

set-cookiecookie

接下来咱们来讲说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数量通常也是有数量限制的,ie八、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的原理和应用场景进行了说明,依然延续以往的“一篇文章只说一件事”的习惯(程序员的事,怎么能叫偷懒呢,这叫模块化封装)。但愿能对看完的同窗有所帮助(就算是只收获了表情包也是极好的)。顺便说一下,前一篇文章彷佛效果不错,骗到了不少收藏和点赞,很是开心(再次疯狂暗示


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

相关文章
相关标签/搜索