Cookie,Session,localStorage,sessionStorage,IndexDB一锅端

317 阅读10分钟

一.Cookie

Cookie概念

概念:本质上是一个存储在浏览器的一个很小的文本文件(也有可能是本地),内部以键值对的形式储存着用户状态。

Cookie产生原因

原因:HTTP是一种无状态的协议,没法保存请求响应的上下文信息,可有些时候需要保存之前的状态,为了解决这个问题引入了Cookie。Cookie的出现解决了客户端与服务端会话状态的问题。

Cookie首部字段

主要有两个

  • Set-Cookie
  • Cookie

Set-Cookie

作用:在响应报文首部设置要传递给客户端的Cookie信息

例如:

Set-Cookie: name=xxx; HttpOnly

Cookie

作用:客户端传递给服务端的Cookie信息

例如:

Cookie: name=xxx

交互流程

客户端和服务器关于Cookie的交互流程如下:

  1. 客户端请求服务端
  2. 服务端生成Cookie信息使用 Set-Cookie 添加到响应报文头部上
  3. 客户端在拿到之后保存Cookie
  4. 在下次请求的时候通过把信息写入请求报文头部Cookie字段中传给服务端

Cookie生命周期

  • 默认情况下Cookie是暂时存在的,也就是它们的存储只在浏览器会话期间存在,当用户在关闭浏览器时失效
  • 以使用expiresmax-age来设置Cookie的过期时间

expires=DATE

作用:给Cookie 设置过期时间,一个具体的时间。

默认值:默认为设置的expires的当前时间。

案例:

例如后端代码中:

ctx.cookies.set("token", '112233', {expires: new Date(+new Date() + 1000 * 60 * 60 * 24 * 7),
})

此时接口请求的响应体的首部字段带有:

Set-Cookie: token=112233; expires=Wed Aug 12 2020 21:55:03 GMT
复制代码

max-age=TIME

作用:给Cookie设置过期时间,一段时间,单位是秒,从客户端收到报文开始计算。

默认值:-1

使用方式与expires一样:

例如后端代码中:

ctx.cookies.set("token", '112233', {
	max-age: 36000,
})

此时接口请求的响应体的首部字段带有:

Set-Cookie: token=112233; max-age=36000	

另外,属性值分为以下三种,方便记忆:

  • 0:立即删除这个Cookie
  • 正数:浏览器将其持久化写入Cookie
  • 负数:会话性Cookie

针对于上面👆的三种情况,面试时可能会碰到的问题:

Q1: cookie的max-age属性设置为0会怎样?

A:如果max-age为0,则表示删除该cookiecookie机制没有提供删除cookie的方法,因此通过设置该cookie即时失效实现删除cookie的效果。失效的Cookie会被浏览器从cookie文件或者内存中删除。

Q2:设置了cookie的max-age属性为正数,关闭浏览器会怎样?

A:如果max-age属性为正数,则表示该cookie会在max-age秒之后自动失效。浏览器会将max-age为正数的cookie持久化,即写到对应的cookie文件中。无论客户关闭了浏览器还是电脑,只要还在max-age秒之前,登录网站时该cookie仍然有效。

Q3:设置了cookie的max-age属性为负数,会怎样?

A:如果max-age为负数,则表示该cookie仅在本浏览器窗口以及本窗口打开的子窗口内有效,关闭窗口后该cookie即失效。max-age为负数的Cookie,为临时性cookie,不会被持久化,不会被写到cookie文件中。cookie信息保存在浏览器内存中,因此关闭浏览器该cookie就消失了。cookie默认的max-age值为-1

作用域

对于Cookie的作用域,表示的是给Cookie绑定域名和路径,在发送请求之前若是发现域名或者路径这两个属性不匹配则不会携带Cookie,通俗来说就是在哪些情况下携带Cookie

有关于Cookie作用域的首部字段有哪些呢?

  • domain=域名
  • path=PATH

domain=域名

作用:指定Cookie可以送达的主机名。

例如:

Set-Cookie: domain=.example.com

path=PATH

作用:指定一个URL路径,Cookie首部只会被添加到这个指定URL路径的请求报文首部上。

默认值为:/,也就是所有URL路径都会携带Cookie

例如设置了:

Set-Cookie: name=xxx; path=/docs

那么只有/docs 下的资源才会带有Cookie,而另一个名为/test 的目录下就没有。

安全性

Cookie的安全性也是一个常问的点,这方面涉及到的首部字段的属性主要有:

  • Secure
  • HttpOnly
  • SameSite

Secure

作用:设置了secure属性,表示Cookie只在HTTPS下传输。

例如:

Set-Cookie: name=xxx; secure

HttpOnly

作用:带上HttpOnlyCookie只能通过HTTP协议传输,不能通过JS脚本文件访问(document.cookie)。

例如:

Set-Cookie: name=xxx; HttpOnly

由于设置了HttpOnly标志的Cookie只能使用在HTTP请求过程中,而无法用JS脚本来读取;又因为很多的XSS攻击都是通过盗用Cookie的,所以设置HttpOnly属性也能保护我们Cookie的安全,是一种预防XSS攻击的重要手段吧。

SameSite

作用:用来限制第三方Cookie,一般用来防止CSRF攻击。

默认值:Chrome80之前一直是None,在Chrome80之后为Lax

例如:

Set-Cookie: name=xxx; SameSite=Lax

SameSite可以设置为三个值,StrictLaxNone

  1. Strict模式下,浏览器完全禁止第三方请求携带Cookie。比如请求xiaohei.com网站只能在xiaohei.com域名当中请求才能携带 Cookie,在其他网站请求都不能。
  2. Lax模式,就宽松一点了,但是只能在get 方法提交表单况或者a 标签发送 get 请求的情况下可以携带 Cookie,其他情况均不能。
  3. 在None模式下,Cookie将在所有上下文中发送,即允许跨域发送。
SameSite在使用时需要注意什么?
  • 对于默认值,Chrome80之前一直是None,在Chrome80之后为 Lax
  • HTTP接口不支持SameSite=None,必须配合Secure属性,表示只有在HTTPS协议下才发送Cookie
  • 需要进行UA检测,部分浏览器不能加SameSite=NoneIOS12Safari以及老的Chrome浏览器会把SameSite=None当成Same=Strict,所以需要用User-Agent获取浏览器信息对一些浏览器不下发Cookie

Cookie实际的用处

Cookie实际的用处其实非常多,主要有:

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

缺点

  • 容量缺陷。Cookie 的体积上限只有4KB,只能用来存储少量的信息。
  • 性能缺陷。Cookie 紧跟域名,不管域名下面的某一个地址需不需要这个 Cookie ,请求都会携带上完整的 Cookie,使得请求会携带不必要的参数。但是可以通过Domain和Path指定作用域来解决
  • 安全缺陷。由于 Cookie 以纯文本的形式在浏览器和服务器中传递,很容易被非法用户截获。在HttpOnly为false的情况下可以通过JS脚本获取到。

二.Session

Session概念

Session是另一种记录客户状态的机制,不同的是Cookie保存在客户端浏览器中,而Session保存在服务器上。客户端浏览器访问服务器的时候,服务器把客户端信息以某种形式记录在服务器上。这就是Session。客户端浏览器再次访问时只需要从该Session中查找该客户的状态就可以了。

Session产生原因

与Cookie产生原因类似。

交互流程

如果说Cookie机制是通过检查客户身上的“通行证”来确定客户身份的话,那么Session机制就是通过检查服务器上的“客户明细表”来确认客户身份。

  • 服务器就要给每个客户端分配不同的“身份标识”
  • 然后客户端每次向服务器发请求的时候,都带上这个“身份标识”
  • 对于浏览器客户端,大家都默认采用 cookie 的方式,保存这个“身份标识”。

Session与Cookie的区别

  1. cookie数据存放在客户的浏览器上,session数据放在服务器上;
  2. cookie不是很安全,别人可以分析存放在本地的COOKIE并进行 COOKIE欺骗,考虑到安全应当使用session
  3. session会在一定时间内保存在服务器上。当访问增多,会比较占用你服务器的性能。考虑到减轻服务器性能方面,应当使用COOKIE
  4. 单个cookie在客户端的限制是4K,就是说一个站点在客户端存放的COOKIE不能超过4K;
  5. 服务端的session的实现对客户端的cookie有依赖关系的,服务端执行session机制时候会生成session的id值,这个id值会发送给客户端并存储在cookie中。

三.localStorage,sessionStorage与indexDB

localStroage

和Cookie异同

localStorage有一点跟Cookie一样,就是针对一个域名,即在同一个域名下,会存储相同的一段localStorage

不过它相对Cookie还是有相当多的区别的:

  1. 容量。localStorage 的容量上限为5M,相比于Cookie的 4K 大大增加。当然这个 5M 是针对一个域名的,因此对于一个域名是持久存储的。
  2. 只存在客户端,默认不参与与服务端的通信。这样就很好地避免了 Cookie 带来的性能问题安全问题
  3. 接口封装。通过localStorage暴露在全局,并通过它的 setItemgetItem等方法进行操作,非常方便。

应用场景

利用localStorage的较大容量和持久特性,可以利用localStorage存储一些内容稳定的资源,比如官网的logo,存储Base64格式的图片资源,因此利用localStorage

sessionStorage

特点

sessionStorage以下方面和localStorage一致:

  • 容量。容量上限也为 5M。
  • 只存在客户端,默认不参与与服务端的通信。
  • 接口封装。除了sessionStorage名字有所变化,存储方式、操作方式均和localStorage一样。

sessionStoragelocalStorage有一个本质的区别,那就是前者只是会话级别的存储,并不是持久化存储。会话结束,也就是页面关闭,这部分sessionStorage就不复存在了。

应用场景

  1. 可以用它对表单信息进行维护,将表单信息存储在里面,可以保证页面即使刷新也不会让之前的表单信息丢失。
  2. 可以用它存储本次浏览记录。如果关闭页面后不需要这些记录,用sessionStorage就再合适不过了。事实上微博就采取了这样的存储方式。

IndexedDB

IndexedDB是运行在浏览器中的非关系型数据库, 本质上是数据库,绝不是和刚才WebStorage的 5M 一个量级,理论上这个容量是没有上限的。

总结

  1. cookie并不适合存储,而且存在非常多的缺陷。
  2. Web Storage包括localStoragesessionStorage, 默认不会参与和服务器的通信。
  3. IndexedDB为运行在浏览器上的非关系型数据库,为大型数据的存储提供了接口。