初次接触 Cookie

1,125 阅读5分钟

什么是 Cookie

Cookie(复数形态Cookies),中文名称为“小型文本文件”或“小甜饼”,指某些网站为了辨别用户身份而储存在用户本地终端(Client Side)上的数据(通常经过加密)。

这是维基百科对 Cookie 的词条解释,由此我们可以知道,Cookie 其实是一个储存在本地的一个小文件。

Cookie 的起源

早期 Web 开发面临的最大问题之一是如何管理状态。简言之,服务器端没有办法知道两个请求是否来自于同一个浏览器。那时的办法是在请求的页面中插入一个token,并且在下一次请求中将这个token返回(至服务器)。这就需要在form中插入一个包含token的隐藏表单域,或着在URLqurey字符串中传递该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=StrictSameSite=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。

  • 服务器可以通过Expiresmax-age这两个标签将 Cookie 设置成过期的状态,之后浏览器会自动清除

  • JavaScript 可以通过document.cookie来操作 Cookie 删除

  • 可以通过浏览器手动删除

后话

我也是接触 Cookie 不久,对其还不是很熟悉,还有很多地方值得去探讨