完整阅读本文大约需要二十分钟时间,可根据文章结构图直接阅读自己需要的部分。
1. Cookie 产生的背景
所有新技术的出现都是为了解决某一痛点。 ——《前端三昧》
我们都知道,HTTP 协议
是无状态的,服务器无法知道两个请求是否来自同一个浏览器,也不知道用户上一次做了什么,每次请求都是完全相互独立,这严重阻碍了交互式 Web
应用程序的实现。例子:
- 购物车:在典型的网上购物场景中,用户浏览了几个页面,买了一盒饼干和两瓶饮料。最后结帐时,由于
HTTP
的无状态性,不通过额外的手段,服务器并不知道用户到底买了什么。 - 登录状态:我们常用的“记住密码”功能,在以前如果不是用
Cookie
记住了登录凭据,想要实现该功能将会很复杂。
正是为了解决这些交互方面存在的痛点,Cookie
应运而生。
2. Cookie 概述
Cookie
( 也叫Web Cookie
或浏览器 Cookie
)是服务器发送到用户浏览器并保存在本地的一小块数据,它会在浏览器下次向同一服务器再发起请求时被携带并发送到服务器上。
存储 Cookie
是浏览器提供的功能。Cookie
其实是存储在浏览器中的纯文本,浏览器的安装目录下会专门有一个 Cookie
文件夹来存放各个域下设置的 Cookie
(非内存 Cookie
)。
通常,它用于告知服务端两个请求是否来自同一浏览器,或者用来保存一些状态信息,Cookie
使基于无状态的 HTTP
协议记录稳定的状态信息成为了可能。常用的有以下方面:
- 对话(
session
)管理:保存登录、购物车等需要记录的信息。 - 简单的缓存:存储一些简单的业务数据,比如购物车等需要记录的信息。
- 个性化:保存用户的偏好,比如网页的字体大小、背景色等等。
- 追踪:记录和分析用户行为。
Cookie
主要是用来存储状态的。
Cookie
曾一度用于客户端数据的存储,因当时并没有其它合适的存储办法而作为唯一的存储手段。现在来说,这样做虽然可行,但是并不推荐,因为 Cookie
的设计目标并不是这个,它:
- 容量很小( 4KB )
- 缺乏数据操作接口
- 影响性能
客户端储存应该更多的考虑使用 localStorage
、sesseionStorage
和 IndexedDB
。
查看浏览器上存储的 Cookie
的方法如下图:
当然,浏览器可以设置不接受 Cookie
,也可以设置不向服务器发送 Cookie
。window.navigator.cookieEnabled
属性返回一个布尔值,表示浏览器是否打开 Cookie
功能。
// 浏览器是否打开 Cookie 功能
window.navigator.cookieEnabled // true
本文所有的讨论都是在浏览器的
window.navigator.cookieEnabled
为 true 的前提下进行的。
3. Cookie
的工作流程
4. Cookie 的限制
4.1 格式限制
Cookie
只能存储纯文本格式,因为:
- 每条
Cookie
的大小有限制 - 为用户信息安全考虑,
Cookie
中存储的是不可执行语句
4.2 大小和条数限制
由于 Cookie
是保存在客户端上的,所以浏览器加入了一些限制确保 Cookie
不会被恶意使用,同时不会占据太多磁盘空间,所以 Cookie
的数量和大小是有限的。
不同浏览器对 Cookie
数量和大小的限制,是不一样的。一般来说,单个域设置的 Cookie
不应超过 50个,每个 Cookie 的大小不能超过 4KB 。超过限制以后,Cookie
将被忽略,不会被设置。
其限制的原因,主要在于阻止
Cookie
的滥用,而且Cookie
会被发送到服务器端,如果数量太大的话,会严重影响请求的性能。以上这两个限制条件,就是Cookie
为什么会被浏览器自动删除的原因了。
4.3 域限制
不可跨域读取,Cookie
是被哪个域写入的,就只能被这个域及其子域读取。比如:
由 test.com
写入的 Cookie
可以被 test.com
和 test.com/child
读取,而不能被 example.com
读取。
4.4 路径限制
存储 Cookie
时会指定路径,该路径的子级可以读取该 Cookie
,但是它的父级却读取不到——子可以读取父,但父不能拿到子,例如:
由 test.com/parent/child
存储下的 Cookie
,可以被 test.com/parent/child/child
读取,但不能被 test.com/parent
读取。
一般会将
Cookie
存在根路径下,可以避免这种情况的发生。