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

在Web应用开发中,如何选择一个合适的Web存储方案呢?文章介绍了Cookie、WebStorage和IndexedDB等常见的Web存储技术。包括它们的技术背景、原理和应用场景,理解这些知识将有助于我们制定更合理的Web方案。

一. Cookie

1. 技术背景

​ Cookie解决了HTTP协议无状态的问题:即HTTP请求/响应本身不保存会话状态。对于交互式Web应用,会话状态一般会随着用户操作发生改变的。例如以下场景:

  • 用户登录状态:当用户登录后,刷新或进入下一页面时,服务端如何判断当前请求的用户登录状态呢?

  • 购物车:当用户选中商品后,进入下个页面继续购物时,服务端如何获取用户在上一页面选中的商品呢?

​ 而Cookie就是解决HTTP协议无状态的一种方法。Cookie是存储在浏览器本地的数据,通过HTTP请求报文头传递到服务端。以上面的用户登录状态为例:

​ 当用户登录后,服务端生成一个Cookie并返回给浏览器,浏览器下次请求时带上Cookie,这样服务端就可以通过Cookie信息判断用户登录状态。

PS:一般把真实信息存放在数据库,然后关联一个token存放到Cookie中。

2. 概念和应用场景

​ Cookie是服务端返回给浏览器并保存在本地的数据,浏览器下次请求同一服务端时会携带Cookie传递给服务端。通常,它用于告知服务端两个请求是否来源于同一浏览器

常见应用场景:

  • 会话状态管理:用户登录状态和购物车功能。
  • 跟踪用户操作行为:广告精准投放(下文会分析)。

3. 原理

​ 当服务端接收到 HTTP 请求时,可以通过 Set-Cookie响应报文头设置Cookie信息。浏览器收到响应后会保存 Cookie,之后对该服务端的每一次请求都通过 Cookie请求报文头携带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

PS:浏览器端也可以通过document.cookie api读写cookie。

4. 生命周期

  • 会话期 Cookie :仅在会话期内有效,浏览器关闭之后它会被自动删除。不需要指定ExpiresMax-Age
  • 持久性 Cookie:在指定ExpiresMax-Age后才失效。

示例:

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

5. 作用域

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

示例:

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

  • Cookie禁止跨域。当domain指定为第三方域名时无效。例如:在a.example.com网站设置domain为b.example.com时无效。

6. 安全属性

​ 与Cookie相关的安全问题有:man-in-the-middle attackXSSCSRF。对应的Cookie安全属性有:

6.1. Secure

防止man-in-the-middle attack。

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

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

6.2. HttpOnly

防止XSS。

​ HttpOnly属性表示不允许浏览器端脚本读写Cookie,这可以防止XSS(跨站脚本攻击)。

​ PS:Cookie本职工作就是帮助服务端辨别请求来源的,对浏览器端程序应该是透明的,这种情况应该带上HttpOnly属性。

6.3. SameSite

防范第三方Cookie存在的CSRF风险

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

  1. 当用户在银行网站bank.example.com登录后保存Cookie。
Set-Cookie:token=jeif;domain=bank.example.com
  1. 此时用户再去访问含有以下标签的恶意网站attack.com:
<img src="http://bank.example.com/transferAccount" />
  1. 则会携带Cookie向银行网站发起转账请求。如果银行不做安全校验的话,那么用户银行账户的钱可能会被转走。

SameSite有以下三个值:

  • None:不限制第三方Cookie。

  • Strict:只有在domain指定域名中发起的请求才能携带Cookie。

  • Lax(默认值),与 Strict 类似,但允许在第三方网站中导航至目标URL时携带Cookie。

​ Strict是严格限制第三方Cookie的,这会导致从外部站点导航至目标URL时,都要重新登录。默认使用Lax,允许在第三方网站中,导航到目标网站的get请求携带Cookie,例如

get请求。但禁止