谈一谈前端存储Web Storage和cookie

2,367 阅读9分钟

前言

有时候我们写的项目,为了提高性能,需要将某个常用的数据存储到浏览器缓存中,那么如何将数据存储到浏览器中呢,本篇文章就是来介绍向浏览器中存储数据的几种方法,还有它们之间的相同点和不同点。

sessionStorage 和 localStorage

先来了解一下什么是 Web Storage。

Web Storage 包含如下两种机制:

  • sessionStorage 为每一个给定的源(given origin)维持一个独立的存储区域,该存储区域在页面会话期间可用(即只要浏览器处于打开状态,包括页面重新加载和恢复)。
  • localStorage 同样的功能,但是在浏览器关闭,然后重新打开后数据仍然存在。

这两种机制是通过 Window.sessionStorageWindow.localStorage 属性使用(更确切的说,在支持的浏览器中 Window 对象实现了 WindowLocalStorage 和 WindowSessionStorage 对象并挂在其 localStorage 和 sessionStorage 属性下)—— 调用其中任一对象会创建 Storage 对象,通过 Storage 对象,可以设置、获取和移除数据项。对于每个源(origin)sessionStorage 和 localStorage 使用不同的 Storage 对象——独立运行和控制。

WebStorage的优点:

(1)存储空间更大:cookie为4KB,而WebStorage是5MB;

(2)节省网络流量:WebStorage不会传送到服务器,存储在本地的数据可以直接获取,也不会像cookie一样每次请求都会传送到服务器,所以减少了客户端和服务器端的交互,节省了网络流量;

(3)对于那种只需要在用户浏览一组页面期间保存而关闭浏览器后就可以丢弃的数据,sessionStorage会非常方便;

(4)快速显示:有的数据存储在WebStorage上,再加上浏览器本身的缓存。获取数据时可以从本地获取会比从服务器端获取快得多,所以速度更快;

(5)安全性:WebStorage不会随着HTTP header发送到服务器端,所以安全性相对于cookie来说比较高一些,不会担心截获,但是仍然存在伪造问题;

(6)WebStorage提供了一些方法,数据操作比cookie方便;

「示例」:

下面的代码片段访问了当前域名下的本地 Storage 对象,并通过 localStorage.setItem() 增加了一个数据项目。(sessionStorage相同)

localStorage.setItem('myCat', 'Tom');

该语法用于读取 localStorage 项,如下:

let cat = localStorage.getItem('myCat');

该语法用于移除 localStorage 项,如下:

localStorage.removeItem('myCat');

该语法用于返回存储中的第 n 个键名,如下:

localStorage.key(0)

该语法用于移除所有的 localStorage 项,如下:

// 移除所有
localStorage.clear();

「相同点」:

  • localStorage和sessionStorage 的存储数据大小一般都是5MB
  • localStorage和sessionStorage 都是本地存储,保存在客户端,不与服务器进行交互通信。
  • localStorage和sessionStorage 只能存储字符串类型,对于复杂的对象可以使用ECMAScript提供的JSON对象的stringify和parse来处理。

「区别」:

  • localStorage 生命周期是永久,除非自己删除或清除缓存,而sessionStorage 仅在当前会话下有效,关闭页面或浏览器后被清除。
  • 浏览器的不同页面间可以共享相同的 localStorage(页面属于相同域名和端口),但是不同页面或标签页间无法共享sessionStorage的信息。
  • localStoragese 常用于长期登录(+判断用户是否已登录),适合长期保存在本地的数据,而 sessionStorage 敏感账号一次性登录。

Web Storage 注意点:

  • Web Storage 只能存字符串,存取 JSON 数据需配合 JSON.stringify() 和 JSON.parse();
  • 遇上禁用 setItem 的浏览器,需要使用 try...catch 捕获异常;

cookie

维基百科上是这样解释的,Cookie(复数形态Cookies),又称为“小甜饼”。类型为“小型文本文件”,指某些网站为了辨别用户身份而储存在用户本地终端(Client Side)上的数据(通常经过加密)。由网景公司的前雇员卢·蒙特利在1993年3月发明。最初定义于RFC 2109。目前使用最广泛的 Cookie标准却不是RFC中定义的任何一个,而是在网景公司制定的标准上进行扩展后的产物。

再来介绍一下设置cookie和获取cookie的方法。

创建 cookie 如下所示:

document.cookie="username=John Doe";

我们还可以为 cookie 添加一个过期时间(以 UTC 或 GMT 时间)。默认情况下,cookie 在浏览器关闭时删除:

document.cookie="username=John Doe; expires=Thu, 18 Dec 2043 12:00:00 GMT";

还可以使用 path 参数告诉浏览器 cookie 的路径。默认情况下,cookie 属于当前页面。

document.cookie="username=John Doe; expires=Thu, 18 Dec 2043 12:00:00 GMT; path=/";

删除 cookie 非常简单。您只需要设置 expires 参数为以前的时间即可,如下所示,设置为 Thu, 01 Jan 1970 00:00:00 GMT:

document.cookie = "username=; expires=Thu, 01 Jan 1970 00:00:00 GMT";

为了方便我们可以把一些方法封装成一个函数,比如下面我们对设置cookie和获取cookie的方法进行了一个封装。

「设置 cookie 值的函数」:

// 该函数设置了 cookie 名、cookie 值、cookie过期时间
function setCookie(cname,cvalue,exdays)
{
  var d = new Date();
  d.setTime(d.getTime()+(exdays*24*60*60*1000));
  var expires = "expires="+d.toGMTString();
  document.cookie = cname + "=" + cvalue + "; " + expires;
}

「获取 cookie 值的函数」:

function getCookie(cname)
{
  var name = cname + "=";
  var ca = document.cookie.split(';');
  for(var i=0; i<ca.length; i++) 
  {
    var c = ca[i].trim();
    if (c.indexOf(name)==0) return c.substring(name.length,c.length);
  }
  return "";
}

最后再来结合实际使用来讲一下cookie。

1. cookie使用场景

客户端请求服务器,如果服务器需要记录该用户状态,就向客户端浏览器颁发一个Cookie。客户端浏览器会把Cookie保存起来。当浏览器再请求该网站时,浏览器把请求的网址连同该Cookie一同提交给服务器。服务器检查该Cookie,以此来辨认用户状态。服务器还可以根据需要修改Cookie的内容。(也就是给你一个身份证,上面记录了你的信息,每次跟后台的交流前,后台都要看看你的身份证过期了没,然后才跟你通话。)

2. cookie的不可跨域名性

既然这些信息都是存放在我们的客户端(浏览器)上,那么浏览器上面存放了这么多的cookie,就不会混乱吗,比如我访问qq的网址,拿了阿里的cookie(身份证),就过去了?

答案是不会的,浏览器的合格与否,就是要看看它的cookie是否会存放和使用好。跨域的cookie是不能够共享的。

3. cookie安全性

既然是存放在客户端上,那么就会存在被修改的危险,如果这个cookie是明文存放的,那么我相信小白也能够随意更改信息(相当于你把你的身份证改成了别人的名字,然后就冒充那个人去跟后台交流)。

早期的cookie确实存在这样的问题,但是肯定要进步,就给加密起来了,现在你的cookie上面都是乱码,只有后台程序才知道这个乱码要怎么解密,变成你的身份,我们乱修改就会导致你的身份证失效。

4. cookie的效率

由于每次跟后台访问的时候,都要携带上这个cookie,我们坐一个假设,如果我们的cookie是5kb,然后我打开一个网站的首页,它上面是首页要请求的次数是200多次,那么在打开首页的过程中,就要消耗5kb×200多=1mb多的流量。

我们才只是打开一个页面而已,光是身份证验证就已经消耗了1MB的流量了,而且还没算上200多次请求返回来的数据流量,算上图片,文字还有其它的,你打开一次首页就要消耗几MB。

所以我们要将cookie的大小压缩一下,不必要的就不放进去了,太浪费流量和效率了。

5. cookie和sessionStorage、localStorage的异同

「相同点」:

  • cookie 和 sessionStorage,localStorage 都是保存在浏览器端、且同源的。

「不同点」:

  • cookie 数据始终在同源的http请求中携带(即使不需要),即 cookie 在浏览器和服务器间来回传递,而 sessionStorage和localStorage 不会自动把数据发送给服务器,仅在本地保存。cookie数据还有路径(path)的概念,可以限制cookie只属于某个路径下。
  • 存储大小限制也不同,cookie 数据不能超过4K,同时因为每次http请求都会携带 cookie、所以 cookie 只适合保存很小的数据,如会话标识。sessionStorage 和 localStorage 虽然也有存储大小的限制,但比 cookie 大得多,可以达到5M或更大。
  • 数据有效期不同,sessionStorage:仅在当前浏览器窗口关闭之前有效;localStorage:始终有效,窗口或浏览器关闭也一直保存,因此用作持久数据;cookie:只在设置的cookie过期时间之前有效,即使窗口关闭或浏览器关闭
  • 作用域不同,sessionStorage 不在所有同源窗口中共享,localstorage 在所有同源窗口中都是共享的;cookie 也是在所有同源窗口中都是共享的。
  • web Storage 支持事件通知机制,可以将数据更新的通知发送给监听者。
  • web Storage 的 api 接口使用更方便。

关于 cookie 和 sessionStorage、localStorage 实际应用可能更像下面这幅图中这样。

总结

最后用一张表格来做个总结📝。

sessionStorage localStorage cookie
生命周期 浏览器关闭 永久存在,除非自己删除或清除缓存 可以自己设置,默认到浏览器关闭
大小限制 5MB 5MB 4K
与服务器通信 仅在客户端 仅在客户端 每次请求都会携带
安全性 相对于cookie来说高一些,不用担心截获,但是仍然存在伪造问题 相对于cookie来说高一些,不用担心截获,但是仍然存在伪造问题 安全性较低(Cookie欺骗,Cookie截获)
应用场景 敏感账号一次性登录 常用于长期登录(+判断用户是否已登录) 判断用户是否登陆过网站

参考文章: