发现不少地方在介绍cookie的做用时,都喜欢使用购物车的例子,那咱们也不妨从这个例子开始提及。程序员
场景示例:有用户a和b,都登录了某个购物网站,此时若是两个用户都点击了【查看购物车】按钮,那么此时服务器就同时收到了2个请求,请求的内容都是:“请告诉我个人购物车有什么商品”。如今问题来了——服务器怎么区分哪一个请求对应哪一个用户呢?web
其实这就是常常看到的那句话http协议是无状态的。为何说无状态呢,由于http
协议能够当作一种简单的应答模式:chrome
那么服务端知道两次访问的客户端是否是同一个吗?显然是母鸡呀!数据库
为了解决这个问题,就要介绍今天的主角--Cookie。数组
能够联想一下生活中。咱们若是去一家生意火爆的火锅店吃火锅的场景(我突然有点想去吃个火锅再回来写了),这时若是有空座了,店员怎么知道在门口等候的顾客应该轮到谁了呢?很简单,在顾客等候以前,先发个号码牌,后面根据号码辨别身份。浏览器
?!!缓存
看到这里,是否是以为有点饿了?啊呸,是否是以为灵光乍现,上面说的问题和这个场景不是一模一样吗?因此,为了可以让会话能够被识别,http中也引入了一个号码牌——cookie
的机制。(会话这个词出现地有点突兀,简单解释下:a用户登陆购物网站以后,接下来发生的一系列请求,都应该属于服务端与a的会话)安全
好了,原理大概说完了,那cookie
具体怎么实现呢?很简单,放在http
的头部(headers)
。在前一篇讲状态码时,已经稍稍涉猎了一点http
头部的相关知识,简单的来讲http
的头部是一个js对象,里面存放了一系列的键值对(key:value)用来表示各类信息,http的【请求】和【响应】都有头部,而cookie机制的实现,则是借助了其中的两个字段:Cookie和Set-Cookie,整个运行流程能够分红如下步骤:服务器
http
请求到服务端(我去告诉店员,我要吃火锅了)在上述过程当中,可能同时也有其余号码牌的顾客在与服务员进行相似的交流过程,因为服务员发给每一个顾客的号码牌上的数字都是惟一的,因此没必要惧怕弄混。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字段,由于cookie已经被缓存了(能够去前面的设置里再看看),而请求头里多了一个cookie字段。(这就是使用号码牌的步骤了)。
接下来咱们把面板的请求类型切换到xhr
,再点点页面上的功能,好比收藏本文,或者给做者点赞、打赏(疯狂暗示)等等。 能够看到请求里都带上了cookie这个头部。
直到cookie过时,或者下次咱们又手动删除这个站点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
test_cookie=CheckForPermission
,表示这个cookie的键值对,每一个cookie都会有本身的名称和值expires=Mon, 25-Feb-2019 00:28:09 GMT
表示cookie的有效期,这个值若是不指定,那么默认值为到浏览器关闭以前为止 path=/
,将服务器上的某个文件目录做为cookie的使用对象(这么抽象的解释确定是书上说的),简单的来讲,是指定服务端有权限访 问Cookie的路径,例如/session/,表示只有/session/下才能够访问cookie,默认为文档所在的目录。domain=.doubleclick.net
,表示cookie所在的域。默认为建立cookie的域。也就是请求地址,好比前面的segment.com
secure
,这个属性前面没有,表示只在https安全通讯时才发送cookiehttpOnly
,这个属性前面也没有,是用来限制使用脚本访问cookie的,设置了这个值后,没法在浏览器客户端使用js
的document.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的文章都会提到这两个例子,可是不多有具体的说明大概是怎么实现的。这里作下简单的介绍。
假设某网站登陆时,提供了一个能够勾选的【7天内免登陆】复选框,用户勾选并正确登陆以后的流程大概是这样的:
服务端接收请求后,建立一个id好比111,用于表示当前发送请求的客户端,并存在服务端的某个位置,简单点能够认为就存在一个名叫sessions
的数组里面吧。以后,把这个id放在响应的set-cookie里面返回。例如:
set-cookie:sessonId=111
同时,服务端设定数组sessions
中的保存的111在7天后删除
客户端收到这个cookie以后保存,以后再次访问的时候都带上这个cookie,服务端接收到cookie里附带的sessionId=111后,去sessions
数组查询是否含有111,
(其实在上面已经悄咪咪的说了一丢丢session的内容,可是本着每次着重说明一个知识点、尽可能剥离无关内容的原则,依然不在本文插入session的相关知识)
本文已经屡次提到购物车了,可是细心的朋友能够看到,这里的前面添加了“未登陆”,那登陆时候为何不用呢?由于咱们前面比较优缺点的时候,有提到cookie毕竟只能存储在发送请求的那个客户端设备,而电商网站通常是容许多终端登陆的(x宝,x猫,x夕夕等),若是使用cookie来保存登陆后的购物车内容,那更换设备的时候就没法查到了,因此登陆状态下的购物车通常是存到数据库中的,只在离线的时候使用cookie的方式来处理比较合适。
核心思路:
js读写cookie的方法处处都有,随便搜索下应该就能找到,本文仍是着重于说明cookie的原理,就不在此赘述了。
本文对cookie的原理和应用场景进行了说明,依然延续以往的“一篇文章只说一件事”的习惯(程序员的事,怎么能叫偷懒呢,这叫模块化封装)。但愿能对看完的同窗有所帮助(就算是只收获了表情包也是极好的)。顺便说一下,前一篇文章彷佛效果不错,骗到了不少收藏和点赞,很是开心(再次疯狂暗示)
惯例:若是内容有错误的地方欢迎指出(以为看着不理解不舒服想吐槽也彻底没问题);若是有帮助,欢迎点赞和收藏,转载请征得赞成后著明出处,若是有问题也欢迎私信交流,主页有邮箱地址