什么是 Cookie
Cookie(复数形态Cookies),中文名称为“小型文本文件”或“小甜饼”,指某些网站为了辨别用户身份而储存在用户本地终端(Client Side)上的数据(通常经过加密)。
这是维基百科对 Cookie 的词条解释,由此我们可以知道,Cookie 其实是一个储存在本地的一个小文件。
Cookie 的起源
早期 Web 开发面临的最大问题之一是如何管理状态。简言之,服务器端没有办法知道两个请求是否来自于同一个浏览器。那时的办法是在请求的页面中插入一个token,并且在下一次请求中将这个token返回(至服务器)。这就需要在form中插入一个包含token的隐藏表单域,或着在URL的qurey字符串中传递该token。这两种办法都强调手工操作并且极易出错。
Lou Montulli,那时是网景通讯的一个雇员,被认为在1994年将 “magic cookies” 的概念应用到了 Web 通讯中。他意图解决的是 Web 中的购物车,现在所有购物网站都依赖购物车。他的最早的说明文档提供了一些 Cookies 工作原理的基本信息该文档在 RFC2109 中被规范化(这是所有浏览器实现 Cookies 的参考依据),并且最终逐步形成了REF2965。Montulli 最终也被授予了关于 Cookies 的美国专利。网景浏览器在它的第一个版本中就开始支持 Cookies,并且当前所有 Web 浏览器都支持 Cookies。
Cookie 的特点
服务器通过
Set-Cookie响应头设置 Cookie
浏览器得到 Cookie 之后,每次请求都要带上 Cookie,无形中增加了流量
服务器读取 Cookie 就知道登录用户的信息
由于在 HTTP 请求中的 Cookie 是明文传递的,所以安全性成问题,除非用 HTTPS
Cookie 的大小限制在 4KB 左右,对于复杂的存储需求来说是不够用的
除了这些特点之外,还有
不同浏览器的 Cookie 不共享
Windows 的 Cookie 储存在C盘的一个文件夹中
Cookie 可以作假
Cookie 有有效期,一般是20分钟。浏览器可自行设置,后端也可以强制设置有效期
后端可以设置 Cookie 的有效期,是否只允许 HTTPS 链接,是否允许 JS 修改等等
如何设置 Cookie
语法
Set-Cookie: <cookie-name>=<cookie-value>
Set-Cookie: <cookie-name>=<cookie-value>; Expires=<date>
Set-Cookie: <cookie-name>=<cookie-value>; Max-Age=<non-zero-digit>
Set-Cookie: <cookie-name>=<cookie-value>; Domain=<domain-value>
Set-Cookie: <cookie-name>=<cookie-value>; Path=<path-value>
Set-Cookie: <cookie-name>=<cookie-value>; Secure
Set-Cookie: <cookie-name>=<cookie-value>; HttpOnly
Set-Cookie: <cookie-name>=<cookie-value>; SameSite=Strict
Set-Cookie: <cookie-name>=<cookie-value>; SameSite=Lax
在 Cookie 的设置中,后面的选项是可选的,且可同时多选。
- 解释
<cookie-name>=<cookie-value>:
<cookie-name>可以是除了控制字符 (CTLs)、空格 (spaces) 或制表符 (tab)之外的任何 US-ASCII 字符。同时不能包含以下分隔字符: ( ) < > @ , ; : \ " / [ ] ? = { }。
<cookie-value>是可选的,如果存在的话,那么需要包含在双引号里面。支持除了控制字符(CTLs)、空格(whitespace)、双引号(double quotes)、逗号(comma)、分号(semicolon)以及反斜线(backslash)之外的任意 US-ASCII 字符。
Expires=<date>:
Cookie 的最长有效时间,形式为符合 HTTP-date 规范的时间戳。如果没有设置这个属性,那么表示这是一个会话期 Cookie 。一个会话结束于客户端被关闭时,这意味着会话期 Cookie 在彼时会被移除。
Max-Age=<non-zero-digit>:
在 Cookie 失效之前需要经过的秒数。一位或多位非零(1-9)数字。
Domain=<domain-value>:
指定 Cookie 可以送达的主机名。假如没有指定,那么默认值为当前文档访问地址中的主机部分(但是不包含子域名)。
Path=<path-value>:
指定一个 URL 路径,这个路径必须出现在要请求的资源的路径中才可以发送 Cookie 首部。
Secure:
一个带有安全属性的 Cookie 只有在请求使用 SSL 和 HTTPS 协议的时候才会被发送到服务器。然而,保密或敏感信息永远不要在 HTTP Cookie 中存储或传输,因为整个机制从本质上来说都是不安全的,比如前述协议并不意味着所有的信息都是经过加密的。
HttpOnly:
设置了 HttpOnly 属性的 Cookie 不能使用 JavaScript 经由 Document.cookie 属性、XMLHttpRequest 和 Request APIs 进行访问,以防范跨站脚本攻击(XSS)。
SameSite=Strict、SameSite=Lax:
允许服务器设定一则 Cookie 不随着跨域请求一起发送,这样可以在一定程度上防范跨站请求伪造攻击(CSRF)。
用法
response.setHeader('Set-Cookie', `sign_in_email=${email}`)
当我们模拟登陆时,就可以看到响应头里面的 Cookie

同样,在跳转网站请求头中也可以看到这个 Cookie

- 利用JavaScript来修改Cookie
如果没有设置不允许修改 Cookie 的话,是可以利用 JavaScript 来修改 Cookie
document.cookie="sign_in_email=789@yyzcl.com"
此时刷新页面看看

此时可以看到,Cookie 被 JavaScript 修改了
但可以通过设置禁止 JavaScript 来修改 Cookie
response.setHeader('Set-Cookie', `sign_in_email=${email}; HttpOnly`)
这样就无法通过 JavaScript 来修改 Cookie

但是还是可以手动地来修改

再刷新页面看看

Cookie是可以人为地伪造地,所以说 Cookie 是不安全的
设置过期时间
可以通过 Cookie 的以下属性来设置过期时间。
Set-Cookie: <cookie-name>=<cookie-value>; Expires=<date>
Set-Cookie: <cookie-name>=<cookie-value>; Max-Age=<non-zero-digit>
-
Expires指定了一个日期/时间, 在这个日期/时间之后 Cookie 过期 -
max-age指定了一个秒数,经过此秒数后 Cookie 过期 -
如果不设置这个标头,则默认关闭浏览器后 Cookie 过期
删除 Cookie
有多种方式来删除 Cookie。
-
服务器可以通过
Expires、max-age这两个标签将 Cookie 设置成过期的状态,之后浏览器会自动清除 -
JavaScript 可以通过
document.cookie来操作 Cookie 删除 -
可以通过浏览器手动删除
后话
我也是接触 Cookie 不久,对其还不是很熟悉,还有很多地方值得去探讨