随着浏览器存储技术的提升,cookie存储数据的功能已经很难满足开发所需,逐渐被WebStorage、IndexedDB所取代,以下介绍这几种存储方式的差异和优缺点。
一、Cookie
Cookie 的来源
Cookie 的本职工作并非本地存储,而是 "维持状态"。
因为 HTTP 协议是无状态的,HTTP 协议自身不对请求和响应之间的通信状态进行保存,通俗来说,服务器不知道用户上一次做了什么,这严重阻碍了交互式 Web 应用程序的实现。
我们可以把 Cookie 理解为一个存储在浏览器里的一个小小的文本文件,它附在HTTP请求上,在浏览器和服务器之间"飞来飞去"。它可以携带用户信息,当服务器检查 Cookie 的时候,便可以获取到客户端的状态。
什么是Cookie及应用场景
HTTP Cookie(也叫 Web Cookie 或浏览器 Cookie)
是服务器发送到用户浏览器并存储在本地的一小块数据(通常经过加密),它会在浏览器下次向同一服务器再发请求的时候被携带并发送到服务器上,通常,它用于告知服务端两个请求是否来自同一浏览器,如保持用户的登陆状态。Cookie 使基于无状态的HTTP协议记录稳定的状态信息称为了可能。
Cookie 以键值对的形式存在
Cookie 主要用于以下三个方面:
- 会话状态管理(如用户登陆状态、购物车、游戏分数或者其他需要记录的信息)
- 个性化设置(如用户自定义设置、主题等)
- 浏览器行为跟踪(如跟踪分析用户行为等)
Cookie的原理以及生成方式
第一次访问网站,浏览器发出请求,服务器响应请求之后,会在响应头里面添加一个 Set-Cookie 选项,将 cookie 放入到响应请求中。
在浏览器第二次发送请求的时候,会通过 Cookie 请求头部将 Cookie 信息发送给服务器,服务端会判别用户身份。
另外,Cookie 的过期时间、域、路径、有效期、适用站点都可以根据需要来指定。
但是我们一般不在 cookie 中存储用户信息(比如用户名,购物车商品等),一方面是 cookie 存储空间有限,单个 cookie 保存的数据不可超过 5k,另一方面是 cookie 安全性低。 我们一般使用 session 来记录用户信息,用 cookie 记录 sessionID。
此时需要引入 session 概念。
什么是 Session
Session 代表着服务器和客户端一次会话的过程。
服务端要创建特定的 Session,是用于标识用户并且跟踪用户。保存在服务端,有一个唯一标识 Session ID。
Session 对象存储特定用户会话所需的属性及配置信息。这样,当用户在应用程序的 Web 页之间跳转时,存储在 Session 对象中的变量将不会丢失,而是在整个用户会话中一直存在下去。
当客户端关闭会话,或者 Session 超时失效时会话结束。
服务端如何识别特定的客户?
这个时候 Cookie 就登场了。每次 HTTP 请求的时候,客户端都会发送相应的 Cookie 信息到服务端。实际上大多数的应用都是用 Cookie 来实现 Session 跟踪的。
第一次创建 Session 的时候,服务端会在 HTTP 协议中告诉客户端,需要在 Cookie 里面记录一个 SessionID,以后每次请求都把这个会话 ID 发送给服务器,我就知道你是谁了。
session 的运行依赖 SessionID,而 SessionID 是存在 cookie 中的
浏览器禁用了 Cookie 怎么办?
-
使用 URL重写的技术来进行会话跟踪,(在url中传递session_id)即每次HTTP交互,URL后面都会被附加上一个诸如 sid=xxxxx 这样的参数,服务端据此来识别用户。
-
Token机制。
Token 的意思是"令牌",是服务端生成的一串字符串,作为客户端进行请求的一个标识。 Token 机制和 Cookie 和 Session 的使用机制比较类似。 当用户第一次登陆后,服务器根据提交的用户信息生成一个 Token,响应时将 Token 返回给客户端,以后客户端只需要带上这个Token前来请求数据即可,无需再次登陆验证。
Cookie 的生成方式
- http response header 中的 set-cookie
- js可以通过 document.cookie 读写 cookie,以键值对的形式展示。
Cookie 的缺陷
-
Cookie 不够大 单个 Cookie 键值对的大小被限制在4KB左右,对于复杂的存储需求来说是不够用的,当Cookie 超过4KB,它将面临被裁切的命运。另外很多浏览器对一个站点的cookie个数也是有限制的。
-
过多的Cookie会带来巨大的性能浪费 Cookie是紧跟域名的,同一个域名下的所有请求,都会携带 Cookie。Cookie虽小,但请求却可以有很多,随着请求的叠加,这样不必要的 Cookie 带来的开销是无法想象的。
-
由于在HTTP 请求中的Cookie 是明文传递的,所以安全性成问题,除非用HTTPS
为了弥补Cookie 的局限性,让“专业的人做专业的事情”,Web Storage 出现了。 HTML5 中新增的本地存储的解决方案 —— Web Storage,它分成两类:sessionStorage 和 localStorage。这样有了 WebStorage 后,cookie只能做它应该做的事情了 —— 作为客户端与服务端交互的通道,保持客户端状态。
二、LocalStorage
特点
- 保存的数据长期存在,下一次访问该网站的时候,网页可以直接读取以前保存的数据。
- 大小为 5M 左右
- 仅在客户端使用,不和服务端进行通信
- 接口封装较好
基于上面的特点,LocalStorage 可以作为浏览器本地缓存方案,用来提升网页首屏渲染速度(根据地第一请求返回时,将一些不变的数据直接存储在本地)。
存入/读取数据
localStorage 保存的数据,以“键值对”的形式存在。也就是说,每一项数据都有一个键名和对应的值。所有的数据都是以文本格式保存。
存入数据
localStorage.setItem("key","value");
读取数据
localStorage.getItem("key");
举个栗子:
<script>
if(window.localStorage){
localStorage.setItem("name","world");
localStorage.setItem("gender","famale");
}
</script>
<body>
<div id="name"></div>
<div id="gender"></div>
<script>
var name = localStorage.getItem("name");
var gender = localStorage.getItem("gender");
document.getElementById("name").innerHTML=name;
document.getElementById("gender").innerHTML=gender;
</script>
</body>
使用场景
LocalStorage 在存储方面没有什么特别的限制,理论上 Cookie 无法胜任的、可以用简单的键值对来存取的数据存储任务,都可以交给 LocalStorage 来做。
举个栗子,考虑到 LocalStorage 的特点之一是持久,有时我们更倾向于用它来存储一些内容稳定的资源,比如图片内容丰富的电商网站会用它来存储 Base64 格式的图片字符串。
三、sessionStorage
sessionStorage 保存的数据用于浏览器的一次会话,当会话结束(通常是该窗口关闭),数据被清空;
sessionStorage 特别的一点在于,即使是相同域名下的两个页面,只要它们不在同一个浏览器窗口中打开,那么它们的 sessionStorage 内容便无法共享。
localStorage、cookie 在所有的同源窗口中都是共享的。
特点
- 会话级别的浏览器存储
- 大小为5M左右
- 仅在客户端使用,不和服务端进行通信
- 接口封装良好 基于上面的特点,sessionStorage 可以有效对表单信息进行维护,比如刷新时,表单信息不丢失。
使用场景
sessionStorage 更适合用来存储生命周期和它同步的会话级别的信息。这些信息只适用于当前会话,当你开启新的会话时,他也需要相应的更新或释放。
sessionStorage、localStorage 和 cookie 之间的区别
共同点:都是保存在浏览器端,且都遵循同源策略
不同点:在于生命周期与作用域不同
作用域:localStorage 只要在相同协议、相同的主机名、相同的端口下,就能读取/修改到同一份localStorage数据。sessionStorage 比localStorage 更严格一些,除了协议、主机名、端口之外,还要求在同一窗口(也就是浏览器的标签页)下。
生命周期:localStorage 是持久化的本地存储,存储在其中的数据是永远不会过期的,使其消失的唯一方法就是手动删除;而 sessionStorage 是临时性的本地存储,它是会话级别的存储,当会话结束(页面被关闭)时,存储内容也随之被释放。
Web Storage 是一个从定义到使用都非常简单的东西。它只能用于存储少量的简单数据。当遇到大规模的、结构复杂的数据时,Web Storage 也爱莫能助了,这时我们就要清楚我们终极大Boss——IndexedDB
四、IndexedDB
IndexedDB是一种低级API,用于客户端存储大量结构化数据(包括文件和blobs),该API使用索引来实现对该数据的高性能搜索。
IndexedDB 是一个运行在浏览器上的非关系型数据库。理论上来说,IndexedDB是没有存储上限的,不仅可以存储字符串,还可以存储二进制数据。
特点
- 键值对存储
- 异步
- 支持事务
- 同源限制
- 存储空间大
- 支持二进制存储