客户端存储 | cookie && WebStorage

cookie用于客户端存储会话信息

服务器在响应HTTP请求时,通过发送Set-Cookie HTTP头部包含会话信息,value和name在发送时都会经过URL编码

1
2
3
4
HTTP/1.1 2.0 OK
Content-type: text/html
Set-Cookie: name=value
Other-header: other-hander-value

浏览器会存储这些会话信息,并在之后每一个请求中都会在HTTP请求头中包含cookie,将cooike信息发回服务器,这些信息可以作为唯一标识发送请求的服务器

1
2
3
GET /index.js HTTP/1.1
Cookie: name=value
Other-header: other-hander-value

cookie的构成

  • name:唯一标识cookie 的名称,cookie 名不区分大小写,cookie 名必须经过URL 编码

  • value:存储在cookie 里的字符串值,这个值必须经过URL 编码

  • domain:cookie 有效的域,发送到这个域的所有请求都会包含对应的cookie,值默认包含子域

  • path:请求URL 中包含这个路径才会把cookie 发送到服务器,默认包含子路径

  • expires/max-age:表示何时删除cookie 的时间戳(即什么时间之后就不发送到服务器了),默认情况下,浏览器会话结束后会删除所有cookie,不过,也可以设置删除cookie 的时间。这个值是GMT 格式(Wdy, DD-Mon-YYYY HH:MM:SS GMT),用于指定删除cookie 的具体时间,这样即使关闭浏览器cookie 也会保留在用户机器上,把过期时间设置为过去的时间会立即删除cookie

  • size:cookie大小

  • secure:设置之后,只在使用SSL 安全连接的情况下才会把cookie 发送到服务器

  • HttpOnly:HttpOnly值为 true 或 false,若设置为true,则不允许通过脚本document.cookie去更改这个值,同样这个值在document.cookie中也不可见,但在发送请求时依旧会携带此Cookie,可防止通过JavaScript访问cookie的值

  • SameSite:用来限制第三方 Cookie,从而减少安全风险,它有3个属性,分别是:

    • Strict:Scrict最为严格,完全禁止第三方Cookie,跨站点时,任何情况下都不会发送Cookie

    • Lax:Lax规则稍稍放宽,大多数情况也是不发送第三方 Cookie,但是导航到目标网址的 Get 请求除外。

    • None:网站可以选择显式关闭SameSite属性,将其设为None,不过,前提是必须同时设置Secure属性(Cookie 只能通过 HTTPS 协议发送),否则无效

  • Priority:优先级,定义了三种优先级,Low/Medium/High,当cookie数量超出时,低优先级的cookie会被优先清除

Web Storage

提出的目的是为了解决通过客户端存储不需要频繁发送回服务器的数据时使用cookie的问题

基于cookie,Web Storage提出了两个目标:

  • 提供在cookie之外的存储会话数据的目标
  • 提供跨会话持久化存储大量数据的机制

Storage类型

Storage类型用于保存名/值对数据,直到存储空间上限(浏览器决定!)

Storage在对象的基础上,增加如下方法:

  • clear():删除所有值;不在Firefox 中实现
  • getItem(name):取得给定name 的值
  • key(index):取得给定数值位置的名称
  • removeItem(name):删除给定name 的名/值对
  • setItem(name, value):设置给定name 的值

sessionStorage对象(跨会话存储)

  • sessionStorage对象只存储会话数据,所以数据只会存储到浏览器关闭

  • 存储在sessionStorage中的数据不受页面刷新影响,可以在浏览器崩溃并重启后恢复

  • 因为sessionStorage对象与服务器会话紧密相关,所以在运行本地文件时不能使用

  • 存储在sessionStorage对象中的数据只能由最初存储数据的页面使用,在多页应用程序中的用处有限

localStorage对象(永久存储)

  • localStorage对象作为在客户端持久存储数据的机制
  • 要访问同一个localStorage对象,页面必须来自同一个域(子域不可以)、在相同的端口上使用相同的协议

存储事件

每当Storage 对象发生变化时,都会在文档上触发storage事件。使用属性或setItem()设置值、使用deleteremoveItem()删除值,以及每次调用clear()时都会触发这个事件

这个事件的事件对象有如下4 个属性

  • domain:存储变化对应的域
  • key:被设置或删除的键
  • newValue:键被设置的新值,若键被删除则为null
  • oldValue:键变化之前的值

可以使用如下代码监听storage事件:

1
2
window.addEventListener("storage",
(event) => alert('Storage changed for ${event.domain}'));

对于sessionStoragelocalStorage上的任何更改都会触发storage事件,但storage件不会区分这两者

总结

三者区别

生命周期

  • cookie:可以通过设置expires/max-age来控制失效时间,没设置就默认关闭浏览器后失效
  • sessionStorage:仅在当前网页会话下有效,关闭页面或者浏览器会被清除
  • localStorage:永久保存,除非手动清除

存放数据大小

  • cookie:4kb左右
  • web Storage:5MB

http请求

  • cookie:每次发送请求的时候都会携带在http头中,如果cookie保存过多数据会带来性能问题
  • web Storage:仅在客户端中保存,不参与和服务器的通信

易用性

  • cookie:需要自己封装,包含get set等方法,详情见红宝书第四版P754页
  • web Storage:原生接口可以接受,也可以再次封装

应用场景

从安全性来说,因为每次http请求都会携带cookie信息,这样无形中浪费了带宽,所以cookie应该尽可能少的使用,另外cookie还需要指定作用域,不可以跨域调用,限制比较多

但是用来识别用户登录来说,cookie还是比stprage更好用的,其他情况下,可以使用storage,就用storage

storage在存储数据的大小上面秒杀了cookie,现在基本上很少使用cookie了

localStorage和sessionStorage唯一的差别一个是永久保存在浏览器里面,一个是关闭网页就清除了信息,localStorage可以用来夸页面传递参数,sessionStorage用来保存一些临时的数据,防止用户刷新页面之后丢失了一些参数