1 Cookie
是什么
HTTP Cookie(也叫 Web Cookie 或浏览器 Cookie)是服务器发送到用户浏览器并保存在本地的一小块数据(一般为4KB),它会在浏览器下次向同一服务器再发起请求时被携带并发送到服务器上。通常,它用于告知服务端两个请求是否来自同一浏览器,如保持用户的登录状态。Cookie 使基于无状态的HTTP协议记录稳定的状态信息成为了可能。
2 Cookie
产生的背景
Cookie
的诞生是为了弥补HTTP无状态的缺点,所谓无状态,是指HTTP协议不对每次请求保存相关信息,浏览器发送的每一次HTTP请求对于服务器来说都是一次新的请求,换句话来说就是服务器根本不知道浏览器上一次发送请求的目的及造成的结果。
3 Cookie
的应用场景
- 会话状态管理(如用户登录状态、购物车、游戏分数或其它需要记录的信息);
- 个性化设置(如用户自定义设置、主题等);
- 浏览器行为跟踪(如跟踪分析用户行为等)。
4 Cookie
的作用范围
Cookie
的作用范围指的是哪些域名下可以使用Cookie
及其使用规则,Cookie
的作用范围主要是靠域名来区分的,最显而易见的是不同域名下的Cookie
是无法共享的,如qq.com
和baidu.com
中的Cookie
是无法共享的。其他使用规则请阅读1.6.3节和1.6.4节,需要注意的是,区分Cookie
作用范围时是不考虑协议和端口的,如http://syzdev.cn
和https://syzdev.cn:8088
两个域名是共享Cookie
的。
5 Cookie
的创建过程
浏览器发送HTTP请求给服务器,当服务器收到HTTP请求后,服务器可以在响应头里面添加一个Set-Cookie
选项,在该选项中可以设置Cookie
的相关属性,详见1.6节。浏览器收到响应后通常会保存该Cookie
,之后每次浏览器对服务器发送请求都会携带该Cookie
,整个过程如下图所示:
6 Cookie
的创建方法
6.1 服务器创建Cookie
客户端给服务器发送HTTP请求后,服务端可以在响应头中添加Set-Cookie
选项,在选项中指定Cookie
的相关选项。
6.2 JavaScript创建Cookie
Cookie
信息保存在document
对象上,可以直接使用document.cookie
访问:
- 创建
Cookie
:
document.cookie = "username=syzdev";
- 查询
Cookie
:将以字符串的形式返回所有Cookie
信息:
let cookieStr = document.cookie; // cookieStr是保存所有Cookie信息的字符串
- 修改
Cookie
:若要修改Cookie
,则需要将原来的Cookie
覆盖:
document.cookie = "username=syz"; // 修改Cookie中的username信息
- 删除
Cookie
:将expires
属性设置为过去的时间或当前的时间,则该Cookie
会被自动删除:
// new Date().toUTCString()获取的就是UTC格式的当前时间
document.cookie = `expires=${new Date().toUTCString()}`;
7 Cookie
的属性
下面说明Cookie
属性的格式及表示方法:
- 自定义属性
Cookie
中的自定义属性是通过键值对的形式保存的,格式如下:
Set-Cookie: key1=value1; key2=value2
- 自带属性
Cookie
中的一些自带属性也是通过键值对的形式保存的,格式如下:
Set-Cookie: Expires=<UTC Date>; Max-Age=<non-zero-digit>
Cookie
中的其他一些自带属性是通过属性名的形式保存的,格式如下:
7.1 Expires
(过期时间)
Expires
属性需要指定一个UTC时间格式的字符串,在这个时间内Cookie
有效,过了这个时间浏览器就会将这个Cookie
删除,如下面例子:
Set-Cookie: Expires=Tue, 22 Mar 2022 14:19:00 GMT
若不指定Expires
属性,则Cookie
只在当前浏览器会话中有效(即浏览器窗口关闭后,浏览器就会删除该Cookie
)。
7.2 Max-Age
(有效时间)
Max-Age
属性需要指定一个数字,表示该Cookie
的有效时间,以秒为单位,可以理解为Cookie
有效时间的倒计时,倒计时结束后,浏览器就会删除该Cookie
,如下面例子表示Cookie
有效时间为30分钟:
Set-Cookie: Max-Age=60*30
7.3 Domain
(域名)
Domain
属性指定了哪些域名可以接收Cookie
,若没有指定Domain
属性,那么其默认值就是当前域名(不包含子域名),所以说指定Domain
属性比不指定Domain
属性的限制少。Domain
属性的使用应遵循如下规则:
- 设置
Domain
:只能是当前域名的上级域名,并且不能为顶级域名或公共域名,如当前域名为s.y.z.qq.com
,可以设置Domain
为s.y.z.qq.com
、y.z.qq.com
或z.qq.com
;但不能是顶级域名com
或公共子域名qq.com
。 - 匹配
Domain
:浏览器在发送Cookie
时,需要根据Domain
属性判断是否需要在发送HTTP请求时携带Cookie
,在匹配域名时,只能是和Domain
相同的域名或是其子域名,如当前Domain
为z.qq.com
,那么可以匹配到z.qq.com
、y.z.qq.com
或s.y.z.qq.com
。
Domain
属性的使用方法如下:
Set-Cookie: Domain=s.y.z.qq.com
需要注意的是:读者可能见过
Domain
中的域名中有前导点,如Domain=.syzdev.cn
,这是浏览器不符合规范的情况,大多数浏览器是不需要加前导点的。
7.4 Path
(路径)
Path
属性指定了域名下哪些路径可以接收Cookie
,这是在Domain
域名已经匹配的情况下,再匹配Path
路径,如Path=/hello
,那么将匹配/hello/s
、/hello/s/y
或/hello/s/y/z
。若不指定Path
属性的值,则Path
的默认值为请求路径,如请求路径为syzdev.cn/hello
,那么Path
属性的值就为/hello
。Path
属性的使用方法如下:
Set-Cookie: Path=/hello
7.5 Secure
(HTTPS安全)
Secure
属性指定只有当前是在HTTPS协议下进行通信,才会在请求中携带Cookie
,Secure
属性的使用方法如下:
Set-Cookie: Secure
7.6 HttpOnly
(脚本安全)
HttpOnly
属性禁止使用JavaScript脚本获取Cookie
,该属性是缓解跨站脚本攻击(XSS)的方式之一,HttpOnly
属性的使用方法如下:
Set-Cookie: HttpOnly
添加该属性后,document.cookie
就无法获取到Cookie
值了。
7.7 SameSite
(禁止第三方Cookie)
SameSite
属性用于限制第三方Cookie
,该属性是缓解跨站请求伪造(CSRF)的方式之一:
Cookie
被分为第一方Cookie
和第三方Cookie
,区分他们的方法是看建立该Cookie
的域名,上文中所提到的都是第一方Cookie
,第三方Cookie
为别的域名所创建的Cookie
,读者可能会疑惑在一个域名下为什么能创建第三方Cookie
以及为什么要创建第三方Cookie
:
- 为什么要创建第三方
Cookie
:广告商或者服务提供商用于追踪用户行为进行个性化广告推荐,如某大型母购物公司旗下又有很多子公司,在用户浏览子公司的域名时,由于子公司的域名和母公司的域名不一样,所以母公司无法获取到子公司下的Cookie
信息,因此使用第三方Cookie
能够在各个子公司下收集用户数据,然后将数据提供给母公司,由母公司来追踪用户行为。- 如何创建第三方
Cookie
:常见的方法是图像、脚本和iframe
。
为了限制这种第三方Cookie
收集数据的行为,所以有了SameSite
属性,该属性有三个可选值:
Set-Cookie: SameSite=Strict|Lax|Node;
Strict
:顾名思义,最为严格的限制,完全禁止使用第三方Cookie
,跨域名访问时,禁止使用Cookie
。Lax
:只有在部分情况下才允许使用Cookie
,如<a>
标签、<link>
标签和get
提交表单。None
:允许使用第三方Cookie
。
7.8 Name
(Cookie名称)
Name
属性用于指定该Cookie
的名称,使用方法如下:
Set-Cookie: Name=cookieName;
7.9 Value
(Cookie的值)
Value
属性用于指定该Cookie
的值,使用方法如下:
Set-Cookie: Value=cookieValue;
8 Cookie
的优缺点
Cookie
的优点:
- 用来弥补HTTP无状态特性的一种方案。
- 存储在客户端,不占用服务器的资源,减少服务器压力。
Cookie
的缺点主要是安全和隐私方面:
- 可以被用户主动禁用浏览器的
Cookie
功能,可以通过window.navigator.cookieEnabled
属性查看当前浏览器Cookie
是否开启。 - 可以被用户直接操作,
Cookie
保存在浏览器,并且是明文存储的,能够直接被用户查看、修改或删除。 - 若
Cookie
中含有关键敏感信息,可能会被不法分子通过跨站脚本攻击(XSS)、跨站请求伪造(CSRF)等手段获取到Cookie
造成严重后果。
关于Cookie
的大小限制,不同的浏览器对于Cookie
的策略不一样,对Cookie
的数量和大小限制也不一样,一般浏览器限制每个域名下的Cookie
数量不超过30个,每个Cookie
的大小不超过4KB,若超过了4KB,内容将被截断,我个人认为这不能算是Cookie
的缺点,只能说是Cookie
的特性,因为Cookie
的诞生并不是为了保存大量数据的,一般情况下4KB完全够用了。