阅读 1502

解密Cookie,这一篇就够了

更多文章以及分享请关注微信公众号 前端er的分享,不止于前端,定期输出一些技术知识、生活感想、理财知识等。

一、Cookie介绍

因为HTTP协议是无状态的,每次请求都是独立的,服务器端无法判断两次请求是否来自同一个用户,进而也就无法判断用户的登录状态,也不知道用户上一次做了什么。所以Cookie就是用来绕开HTTP的无状态性的“额外手段”之一。服务器可以设置或读取Cookies中包含信息,借此维护用户跟服务器会话中的状态。

Cookie 是服务器端发送给客户端的一段特殊信息,这些信息以文本的方式存放在客户端,客户端每次向服务器端发送请求时都会带上这些特殊信息。
具体过程是:客户端发送请求到服务端,然后服务端返回的response headers中会有Set-Cookie这个字段,将 信息写入 Cookie 中。然后在下一次客户端请求接口时,会在request headers里带上这个Cookie字段,这样服务器就可以拿到这些信息,达到了维持状态的目的。
屏幕快照 2020-10-21 14.43.46.png屏幕快照 2020-10-21 14.43.33.png

Cookie 主要用于以下三个方面:

  • 会话状态管理(如用户登录状态、购物车、游戏分数或其它需要记录的信息)
  • 个性化设置(如用户自定义设置、主题等)
  • 浏览器行为跟踪(如跟踪分析用户行为等)

二、Cookie的属性

2.1 domain和path属性

domain 指定了该 Cookie 所属的域名,默认情况下,domain 会被设置为创建该 Cookie 时所在的域名。如果不指定,默认为 origin,不包含子域名。如果指定了Domain,则一般包含子域名。
例如,如果设置 Domain=mozilla.org,则 Cookie 也包含在子域名中(如developer.mozilla.org)。
而 path 则指定了该 Cookie 所属的路径,注意子路径也会被匹配。
例如,设置 Path=/docs,则/docs/Web/ 这个地址也会匹配。
domain 和 path 两者一起来限制了该 Cookie 允许被哪些 URL 访问。

2.2 Expires/Max-Age

Expires :具体到期时间,UTC格式。如果没有设置该选项,则默认有效期为session,即会话cookie,这种cookie在浏览器关闭后就没有了。

Set-Cookie: id=a3fWa; Expires=Wed, 21 Oct 2015 07:28:00 GMT;
复制代码

Max-Age属性指定从现在开始 Cookie 存在的秒数,比如60 * 60 * 24 * 365(即一年)。过了这个时间以后,浏览器就不再保留这个 Cookie。
如果同时指定了Expires和Max-Age,那么Max-Age的值将优先生效。

  • Max-Age为正数: cookie 会在 max-age 秒之后被销毁
  • Max-Age为负数时: cookie 只在浏览器会话期间存在,当用户关闭浏览器窗口后这些值也会随之销毁
  • Max-Age 为 0 时: cookie 将被立即销毁

2.3 SameSite属性

SameSite: Cookie 允许服务器要求某个 cookie 在跨站请求时不会被发送,从而可以阻止跨站请求伪造攻击(CSRF)。
SameSite 可以有下面三种值:

  • None。浏览器会在同站请求、跨站请求下继续发送 cookies,不区分大小写。
  • Strict。浏览器将只发送相同站点请求的 Cookie(即当前网页 URL 与请求目标 URL 完全一致)。
  • Lax。在新版本浏览器中,为默认选项,Same-site Cookies 将会为一些跨站子请求保留,如图片加载或者 iframe 不会发送,而点击a标签会发送;

大多数主流浏览器的SameSite的默认值已经是Lax了。如果想要指定 Cookies 在同站、跨站请求都被发送,现在需要明确指定 SameSite 为 None。(所以不要再问为什么接口返回了Set-Cookie但是却没有设置成功了,大概率原因在这里,曾经遇到过)

2.4 HttpOnly

如果这个属性设置为true,意思就是告之浏览器该 cookie 绝不能通过 JavaScript 的 document.cookie 属性访问。可以避免跨域脚本 (XSS) 攻击。
(面试高频)

2.5 Secure

标记为 Secure的 Cookie 只应通过被 HTTPS 协议加密过的请求发送给服务端。

三、Cookie相关操作

1.创建Cookie:

// 直接使用document.cookie = 设置即可
document.cookie= "test=" + '123';
复制代码

2.读取Cookie:

直接调用函数,例如let cookie = getCookie(); cookie.name即为对应cookie。

// 读取Cookie函数
function getCookie() {
  let cookieArr = document.cookie.split("; "); // 特别注意!cookie中的数据都是以分号加空格区分开 
  let obj = {};
  cookieArr.forEach( v => {
    let arr = v.split("=");
    obj[arr[0]] =  unescape(arr[1]); // unescape 解码
  });
  return obj
}
复制代码

3.删除Cookie:

直接调用:delCookie("xxx");

//删除Cookie
	function delCookie(name){
    // 将 cookie 的 max-age 属性设置 0 来实现对 cookie 的删除
		document.cookie = `${name}=;max-age=0`;
	}
复制代码

在ios系统上面,设置Cookie为汉字时会设置失败,所以需要将汉字进行编码,再储存到Cookie,取出来的时候也需要解码,encode:escape(),decode:unescape()。

四、其他

  • Cookie是跨域的,也就是在不同的域名中,访问的Cookie的时候,只能访问对应的域名的Cookie。
  • 每个Cookie的大小一般不超过4KB,超过以后,Cookie将会被忽略,不会被设置
  • 浏览器每次向服务器发起请求,就会自动附上Cookie

更多文章以及分享请关注微信公众号 前端er的分享,不止于前端,定期输出一些技术知识、生活感想、理财知识等。