可以在浏览器的 Application 面板下看到浏览器的本地存储包含了:CookiesessionStoragelocalStorageIndexedDB

Cookie 又叫 HTTP Cookie 或者叫浏览器 CookieCookie 的作用是维护服务端和客户端的会话状态,简而言之就是告诉服务器当前客户端用户的一些信息,比如是否登录啥的。

Cookie 通常是由服务端生成,然后通过响应头的 Set-Cookie 发送给客户端浏览器:

1
2
3
HTTP/1.0 200 OK
Content-type: text/html
Set-Cookie: my_cookie=bulandent

浏览器会将 Cookie 保存在本地,并且会在下次请求头部的 Cookie 中附上这个值:

GET /home.html HTTP/1.1
Host: www.example.org
Cookie: my_cookie=bulandent

按照 Cookie 的生命周期可以将它分为两类:

  • 会话 Cookie:没有指定过期时间 (Expires)或有效期(Max-Age)的 Cookie,当浏览器关闭后会被自动删除,但是现在很多浏览器都实现了会话恢复功能,即使浏览器关闭,会话 Cookie 也会被保留下来;这种类型的 Cookie 会保存在浏览器的内存中;
  • 持久性 Cookie:通过指定过期时间 (Expires)或有效期(Max-Age)的一种 Cookie,存储于客户端硬盘中。设定的日期和时间是指和客户端系统时间进行比较的。

Cookie 会绑定特定的域名(Domain),除此之外,它还有如下一些限制:

通常,只要遵守以下大致的限制,就不会在任何浏览器中碰到问题:

  • 不超过 300 个 Cookie
  • 每个 Cookie 不超过 4KB;
  • 每个域名下不超过 20 个 Cookie

每个域能设置的 Cookie 总数也是受限的,但不同浏览器的限制不同。例如:

  • 最新版 IE 和 Edge 限制每个域不超过 50 个 Cookie
  • 最新版 Firefox 限制每个域不超过 150 个 Cookie
  • 最新版 Opera 限制每个域不超过 180 个 Cookie
  • Safari 和 Chrome 对每个域的 Cookie 数没有硬性限制。

如果 Cookie 总数超过了单域名的上限,浏览器就会删除之前设置的 Cookie,而删除的逻辑不同浏览器也不大相同。

Cookie 构成除了以上提到的 NameValueDomainExpires/Max-Age 外,还有几个比较重要的需要说下:

  • Path:请求 URL 中包含这个路径才会把 Cookie 发送到服务器;

  • Secure:只有 HTTPS 请求才会发送标记为 SecureCookie

  • HttpOnly:将限制在客户端通过 document.cookie 读取设置为 HttpOnlyCookie

  • SameSite:控制 Cookie 在跨站请求的时候是否会被发送,有 3 个值:

    • None 允许跨站请求发送;
    • Lax:允许跨站 GET 请求发送;
    • Strict:不允许跨站请求发送;

除了服务器能够设置 Cookie 外,客户端也可以通过 document.cookie 设置。

  • Cookie 会被附加在每个 HTTP 请求中,所以无形中增加了流量;
  • 由于在 HTTP 请求中的 Cookie 是明文传递的,所以安全性成问题,除非用超文本传输安全协定;
  • Cookie 的大小限制在 4KB 左右,对于复杂的存储需求来说是不够用的。

黑客常常会利用 Cookie 进行攻击,比如 XSSCSRF 等;所以为了网站安全,通常需要针对 Cookie 做一些安全措施:

  • 对特殊的 Cookie 设置 HttpOnly,防止被客户端脚本读取,比如维护登录状态的 Cookie 就可以这么做;
  • 用于敏感信息(例如指示身份验证)的 Cookie 的生存期应较短,并且 SameSite 属性设置为StrictLax

Web Storage

Web Storage 存在的目的就是为了解决每次向服务器请求的时候都需要携带 Cookie 信息的问题。Web Storage 包含了 2 个对象:sessionStoragelocalStorage。通过这 2 个对象实现了:

  • 提供在 Cookie 之外的存储会话数据的途径;
  • 提供跨会话持久化存储大量数据的机制。

Web Storage 的限制

和其他客户端数据存储方案一样,Web Storage 也有限制。

  • 存储大小:不同浏览器给 sessionStoragelocalStorage 设置了不同的空间限制,但大多数会限制为每个源 5MB;
  • 存储类型:只能存储字符串,所以如果数据是对象结构的,需要通过 JSON.stringify 先转成字符串;
  • 存储限制于同一个源(origin),这也是同源策略的限制之一。即 http://a.comhttps://a.com 存储的 ``Web Storage` 数据是不相同的。

Web Storage 提供了一套详细的 API 使得我们可以很好的进行数据存储:

属性

  • Storage.length:返回一个整数,表示存储在 Storage 对象中的数据项数量。

方法

  • Storage.key(n):该方法接受一个数值 n 作为参数,并返回存储中的第 n 个键名;
  • Storage.getItem():该方法接受一个键名作为参数,返回键名对应的值;
  • Storage.setItem():该方法接受一个键名和值作为参数,将会把键值对添加到存储中,如果键名存在,则更新其对应的值;
  • Storage.removeItem():该方法接受一个键名作为参数,并把该键名从存储中删除;
  • Storage.clear():调用该方法会清空存储中的所有键名。

sessionStoragelocalStorage 都是 Storage 的实例,所以自然而然的它们都拥有上面的属性和方法。

sessionStorage

sessionStorage 对象只会存储会话数据,这意味着当浏览器 tab 页被关闭的时候,对应的 sessionStorage 数据将被清除。除此之外,它还有如下表现:

  • 不受页面刷新(包括强制刷新)影响,并且可以在浏览器崩溃并重启后恢复;
  • 在当前页面通过新标签页或窗口打开一个新页面的时候,新页面会复制父级页面的 sessionStorage 数据;
  • 使用同一个 URL 打开多个标签页,它们各自的 sessionStorage 数据不同;

localStorage

区别于 sessionStoragelocalStorage 的存储不受会话限制而且能够长期存储于客户端浏览器中,直到手动删除或者清除浏览器缓存。

IndexedDB

虽然 Web Storage 在存储较少量的数据很有用,但对于存储更大量的结构化数据来说力不从心,这个时候就需要用到 IndexedDB,它类似于 MySQL,但是和传统数据库最大的区别在于,它是适用对象存储而不是表格保存数据。IndexedDB 也受到源的限制。

和 Web Storage 的区别

  • 存储大小:Web Storage 限制每个源大约 5MB。IndexedDB 的存储空间有 2 个限制:全局限制即为浏览器的最大存储空间一般是可用磁盘空间的 50%;组限制为全局限制的 20%,且它至少有 10MB,最大为 2GB 存储空间;
  • 存储类型:Web Storage 只能存储字符串,IndexedDB 可以存储字符串、BlobArrayBuffer
  • Web Storage 的存储操作是同步进行的;IndexedDB 由于数据量大,所以多数操作都是异步执行的;

参考文章