如何选择一个合适的Web存储方案

936 阅读7分钟

Web客户端存储是一个现代Web应用必不可少的功能,常见的有Cookie、WebStorage和IndexedDB等,如何选择一个合适的Web存储方案呢?

一. Cookie

1. 为什么要有Cookie?

HTTP协议是无状态的,即一次请求和响应就是一次完整地HTTP通信,多个请求之间是没有会话状态的。但是,现代Web应用一般是有会话状态的。例如:

  • 用户身份认证:用户登录后进入下一页面,如何判断当前请求是哪个用户?
  • 购物车:用户选中商品后进入下一页面继续购物,如何获取用户之前选中的商品呢?

所以,就有了Cookie,用于解决HTTP协议无状态的问题。

Cookie是服务器返回并保存在浏览器本地的数据,浏览器下次请求时会自动带上Cookie信息

2. Cookie是怎么实现的?

服务器将Cookie信息存放在 Set-Cookie header,浏览器收到响应后会保存到本地,之后对该服务器的请求都会通过 Cookie header带上Cookie信息。

服务器响应报文:

HTTP/1.0 200 OK
Content-type: text/html
Set-Cookie: yummy_cookie=choco
Set-Cookie: tasty_cookie=strawberry
​
[页面内容]

浏览器请求报文:

GET /sample_page.html HTTP/1.1
Host: www.example.org
Cookie: yummy_cookie=choco; tasty_cookie=strawberry

常见应用场景:

  • 保持会话状态:用户身份认证和购物车功能。
  • 跨站追踪:第三方Cookie追踪用户行为,实现广告精准投放。

例如,当用户登录认证后,服务端生成一个Cookie并返回给浏览器,浏览器下次请求时带上Cookie,这样服务端就识别用户身份信息了。PS:一般把真实信息存放在数据库,然后关联一个token存放到Cookie中。

下面是Cookie的相关属性:

a. 有效期

  • 会话期 Cookie :仅在会话期内有效,浏览器关闭之后它会被自动删除。
  • 持久性 Cookie:在指定有效期Expires或Max-Age后失效。
Set-Cookie: id=a3fWa; Expires=Wed, 21 Oct 2015 07:28:00 GMT;

b. 作用域

domain/path 定义了Cookie的作用域,即允许 Cookie 被发送给哪些域名。domain默认是origin的域名。

set-cookie: token=123; domain=.bing.com;path=/;
  • Cookie可以在子域名之间共享。例如,单点登录,用户在网站boss.com登录后保存Cookie,之后进入子网站a.boss.com时会携带Cookie,服务端就知道是哪个用户了。
  • Cookie是禁止跨域的。即domain为www.a.com的Cookie禁止被发送到www.b.com

c. 安全性

Cookie是存储在浏览器端,并通过HTTP报文在网络上传输,所以需要考虑安全性问题。下面是几种常见的安全问题和Cookie属性。

  1. Secure

Cookie是通过HTTP报文在浏览器和服务器之间传输,有man-in-the-middle attack的风险。 Secure属性要求Cookie 只能被HTTPS请求携带,从而保证Cookie的安全传输。

但是,能访问到客户端硬盘的人依然能读取到Cookie。所以Cookie不应该携带敏感信息

  1. HttpOnly

HttpOnly表示禁止浏览器端脚本读写Cookie,防范XSS(跨站脚本攻击)。

Cookie本来就是给服务器辨别请求来源的,对浏览器端程序应该无感。通常,服务器完成用户身份认证后,设置Set-Cookie header并指定HttpOnly,而不是由前端脚本拿到数据后再去设置Cookie。

  1. SameSite

当Cookie的domain属性不是当前网站域名和父级域名时,称为第三方Cookie,存在CSFR风险。

SameSite有以下三个值:

  • None:不限制第三方Cookie。
  • Strict:禁止第三方Cookie。
  • Lax(默认值),与 Strict 类似,但允许导航到目标网站时携带第三方Cookie。

默认使用Lax,限制第三方Cookie,但允许导航到目标网站时携带第三方Cookie,例如<a>、<link>和<form>get请求。但禁止<img>、<iframe>和ajax等请求携带第三方Cookie。

示例:

Set-Cookie: id=a3fWa; Expires=Wed, 21 Oct 2015 07:28:00 GMT; Secure; HttpOnly;SameSite=Lax;

第三方Cookie常用来跨站追踪。例如:单点登录和广告精准投放。示例:

  1. 用户进入购物网站shopping.boss.com后服务端返回Cookie(domain=.boss.com)。
  2. 之后用户的搜索和点击行为会被记录到数据库。
  3. 当用户访问了嵌入购物网站广告组件的页面时,会携带Cookie请求广告网站ad.boss.com,广告网站根据Cookie找出用户行为生成广告内容返回给浏览器。

3. Cookie的不足之处

  • Cookie容量小

    浏览器对每个站点下的Cookie大小和数量都是有限制的。每个cookie的name=value的value值大概在4k

  • 额外的性能开销

    由于服务器设置 Cookie 后,浏览器的每次请求都会携带 Cookie 数据,会带来额外的性能开销。

4. 小结

Cookie是服务器返回并保存在浏览器本地的数据,浏览器下次请求时会自动带上Cookie信息。通常用来保持会话状态和跨站追踪。

但是Cookie并不适合存储复杂数据,因为其容量小且会产生性能开销。

二. Web Storage

1. 纯粹的客户端存储

过去,Cookie作为惟一的浏览器端存储方案,存储容量小且带来了额外的性能开销,并不适合所有的存储需求。更多时候,我们需要的是一个纯粹的客户端存储功能:即数据存储在浏览器端,不需要在浏览器和服务端之间来回传递。例如实现以下功能:

  • 用户搜索历史记录功能。
  • 存储客户端配置信息。

现在,Web Storage提供了更纯粹的浏览器端存储方案。

2. WebStorage是怎么实现的?

Web Storage通过创建一个Storage对象来存储键值对,key和value是字符串格式。并且该Storage对象只保存在浏览器本地,不会通过HTTP请求传递给服务端。

示例:

// 1.存储值
localStorage.setItem("key","value");
// 2.获取值
var valueLocal = localStorage.getItem("key");
// 3.删除值
Storage.removeItem("key");
// 4.清除Storage对象
Storage.clear();
// 5.Storage对象发送变化时,触发storage事件
window.addEventListener('storage', function(e) {
  document.querySelector('.my-storage').textContent = e.storageArea;
});

a. 有效期

  • sessionStorage :Storage对象仅在页面会话期间有效。
  • localStorage :Storage对象是持久性的。在浏览器重新打开时依然有效。

b. 作用域

Web Storage也受同源策略保护。其中sessionStorage只作用于当前页面,即便打开两个标签页访问同一页面,也会创建两个不同的Storage对象。

c. 存储容量

Storage对象最大容量为5M左右。

3. 应用场景

Web Storage的应用场景:

  • localStorage实现用户搜索历史记录功能。

    image-20220123152526201

  • localStorage实现存储客户端配置信息。

    image-20220123161351449

  • sessionStorage可以作为会话级别的缓存,例如表单信息存储,实现刷新页面不丢失表单数据。

4. WebStorage的不足之处

  • 只能存储字符串类型的数据,不支持其它数据类型。
  • 存储容量只有5M左右。
  • 数据是明文存储,且存在XSS攻击。

5. 小结

WebStorage是纯粹的客户端存储方案,可以满足大部分的存储需求。但面对专业性要求更高的存储需求时,依然存在不足,例如只支持字符串类型,存储容量不够大,数据是明文存储等。

三. IndexedDB

1. 更专业的数据存储

IndexedDB 是一个非关系型数据库,可以存储结构化克隆算法支持的任何对象(包括字符串、ArrayBuffer 对象和 Blob 对象等二进制数据)。支持索引检索。

使用过程包括:指定数据库模式,建立数据库连接,然后检索和更新一系列事务。由于IndexedDB提供的是比较底层的api,所以开发中可以借助第三方库来操作。

四. 总结

  • Cookie 解决的是HTTP协议无状态的问题;
  • Web Storage 提供的纯浏览器端存储的功能,不涉及跟服务端交互;
  • IndexedDB 是更专业的浏览器端存储方案,支持更大的存储容量,更复杂的数据结构。

正是有了这些更专业的浏览器端存储方案的出现,让Web应用的性能进一步的提升,可以承载更加复杂的业务功能。

参考资料

mdn

Cookie 已凉,Web 存储该这么做!