引言
随着对前端的了解越来越深入,了解到了很多种浏览器的存储方案,如 Cookie、LocalStorage等,哪这些存储方案有何异同,分别的适用场景又是什么呢。
Cookie
Cookie的来源
Cookie 被创造出来的本意并不是本地储存,而是为了辨别用户身份。众所周知,Http 协议是无状态的,也就是说你每一次发送给服务器的请求对于服务器来说都是孤立的,服务器不知道这这些请求来自于谁。比如你向购物车里面添加了一些商品,但是当发送结账请求的时候服务器懵了,我怎么知道你是谁,你买了什么呢。而使用 Cookie 之后,服务器就可以通过查看 Cookie 来判断发送用户,一定程度上 Cookies 可以说是请求的身份证。可以告诉服务器请求发送自谁。
Cookie是什么
百闻不如一见,直接来看看 Cookie 长啥样
这是百度首页使用的 Cookie ,如你所见,Cookie 是以 Name-Value 键值对储存在浏览器中的,其中 Value 又是明显经过了加密的数据。
Cookie生成方式
Cookie 是所属于域名的,还是百度首页的 Cookie,通过 Domain 属性可以得知前两个 Cookie 是属于 .baidu.com 的
每个域名只能设置与访问到自己域名下的 Cookie,比如 baidu.com 无法访问 Domain 为 sougou.com 的 Cookie。但是子域名可以读取父域名设置的Cookie,比如截图中 www.baidu.com 就读取到了 Domain='.baidu.com' 的Cookie,通过手动设置 Domain 可以设置父域名的 Cookie,比如 www.baidu.com 可以设置 Domain='baidu.com'
这样 *.baidu.com 所有二级域名也能读取到它设置的 Cookie
//www.baidu.com
document.cookie='age=20;domain=.baidu.com'
// 此时 所有二级域名可以直接读取到这个 Cookie
Cookie的生成方式分为 服务器端生成和浏览器端生成。
- 服务器端-通过设置 http response header中的set-cookie
我们可以通过响应头里的 Set-Cookie 指定要存储的 Cookie 值。当请求返回浏览器的时候浏览器就会按照 header 中的 set-cookie 值设置 Cookie。默认情况下,Domain 被设置为设置 Cookie 页面的主机名,当然我们也可以手动设置 Domain 的值。
Set-Cookie: id=a3fWa;
- 浏览器端- js中可以通过document.cookie可以读写cookie,以键值对的形式展示
document.cookie="id=a3fWa"
document.cookie='age=20;domain=.baidu.com'
Cookie的应用场景
既然 Cookie 的作用就是告诉服务器请求来自于谁,那么最主要的作用就是保持用户登陆态(记住密码),除此之外还可以记录用户浏览数据,进行广告推送和前文提到的购物车等。
Cookie的缺点
缺点其实在前文中就很显而易见了
- 不够大
Cookie 会随着每一次请求发送,这就注定了 Cookie 必定会有严格的大小限制,每一个 Cookie 的大小被限制在了 4kb,值得注意的是 4kb 指的是一个 Name-Value 的大小,而并不是说这个域名可以设置的 Cookie 总大小只有 4kb
- 性能缺陷
Cookie 是跟随着域名的,会随着每一个同域名请求发送,但是其实很大一部分请求,比如说图片等静态资源的请求是完全用不着 Cookie 的,虽然每个Cookie只有 4kb 但是积少成多也会带来巨大的资源浪费。
我们可以把静态资源放到 CDN 上去,这时候图片域名就和主站域名不相同了,就不会附带发送 Cookie
- 不够安全
正如上文直接打开控制台就可以看到 Cookie 一样,Cookie 虽然通过编码进行了加密,但在 Http 传输中是明文传输,脚本也可以很轻松的获取到 Cookie,非常容易被破解。
在服务器端设置 Cookie 的时候附带上 HttpOnly 标记,这样在浏览器端就无法使用 document.cookie 访问到这个 Cookie 了
Set-Cookie: id=a3fWa; HttpOnly
标记为 Secure 的 Cookie 只应通过 Https 协议加密过的请求发送,但是即便如此也不应该使用 Cookie 储存敏感信息,因为 Cookie 有其固有的不安全性,这两个标记也无法提供确切的安全保障。
解决方法
既然 Cookie 有这么多缺点,有没有什么一劳永逸的解决方法呢,那就是「专业的人做专业的事」。
用户登录态和部分用户信息的存储的工作交给 Seesion ---即 Cookie 只用来储存一个用户唯一标识符,真正信息储存在服务器端,使用 Cookie 作为 SeesionID 去服务器查找信息,这样一来 Cookie 的容量限制,安全问题都引刃而解了,因为此时 Cookie 里面就是一串无意义的随机码。
本地储存得工作交由 HTML5 中新增本地存储的解决方案 「Web Storage」 ,它又分成两类 :localStorage 和 SessionStorage ,接下来就介绍这两兄弟。
LocalStorage
特点
- 数据长时间保存,直到手动删除为止
- 大小约为 5M
- 和 Cookie 一样,一个网站只能访问和操作自己网站域名下的数据
- 仅在客户端使用,和服务端无通信
- 接口封装较好
- 使用键值对保存信息
- 同源窗口都可以访问
使用示例
LocalStorage 使用非常方便:
// 设置数据
localStorage.setItem("key","value");
//读取数据
let valueLocal = localStorage.getItem("key");
使用场景
通过上面那些特性就可以看出 LocalStorage 非常适合用来做本地缓存,可以提高首屏加载速度。一些图片等不会经常改变的大资源也可以缓存下来,减少网络请求。
SeesionStorage
特点
- 保存时间为本次会话,也就是说窗口关闭就没了
- 仅本窗口可以访问,同源的其他窗口都不行
- 大小约为 5M
使用场景
sessionStorage 更适合用来存储生命周期和它同步的会话级别的信息。这些信息只适用于当前会话,比如可以用来做表单数据的持久化,防止刷新后表单数据丢失
Cookie、LocalStorage 和SessionStorage 之间的区别
作用域的不同
这三者都遵循协议,即同协议,同域名,同端口下才能访问和修改同一份数据,唯一不同的就是 SeesionStorage 还要求在同一窗口。
生命周期的不同
Cookie 可以手动设置过期时间,默认就是本次会话时长,随着窗口关闭而删除,当设置了过期时间时候,就会被储存到硬盘中直到过期时间才被删除
LocalStorage 是持久化的本地储存,除非你手动删除,否则会一直存在
SessionStorage 是会话级别的存储,也是随着窗口关闭而删除。
总结
这就是几种浏览器存储方案,当然还有我们应该根据不同方案各自的特点决定什么时候使用什么方案,适合的才是最好的。总结一下本文的几个重点
- Cookie 的本职工作并非本地存储,而是“维持状态”
- Web Storage 是 HTML5 专门为浏览器存储而提供的数据存储机制,不与服务端发生通信
参考文章
- Cookie的生命周期问题
- 深入了解浏览器存储
- 把cookie聊清楚