这次在写项目的登录认证过程中,碰到了一点小问题,是关于浏览器存储方面的东西,就仔细查了资料,总结一下。
浏览器本地存储概述
简介
cookie是指某些网站为了辨别用户身份、进行 session 跟踪而储存在用户本地终端上的数据(通常经过加密)。
webStorage
webStorage是HTML5中本地存储的解决方案之一,包括sessionStorag和localStorage,两者差別就差在生命周期的不同而已。
websql和indexeddb
IndexedDB 是一种低级API,用于客户端存储大量结构化数据。该API使用索引来实现对该数据的高性能搜索。webStorage 对于存储较少量的数据很有用,但对于存储更大量的结构化数据来说,这种方法不太有用。IndexedDB提供了一个解决方案。
websql是早期的存储标准,目前已经不再维护,转向indexeddb,不过websql的兼容性更好。不过indexeddb是未来,所以接下来主要讲indexeddb
四者对比
类型 | 生命周期 | 存储大小 | 与服务器通信 | 作用域 | 使用场景 |
---|---|---|---|---|---|
Cookie | 一般由服务器生成,可设置过期时间,默认是关闭浏览器后失效 | 4k左右 | 可每次携带在http头部中,但保存过多数据会带来性能问题 | 可通过.setDomain设置主域名共享 | 不建议在cookie里存储数据,必要时存储同步访问页面时必须要被带到服务端的信息,例如网站的用户登录信息 |
localStorage | 永久保存,除非被清除 | 5m左右 | 只能存储在浏览器端 | 子域名之间相互独立 | 存储用户的一些状态和数据,缓解服务器压力 |
sessionStorage | 仅存在当前标签页下,关闭浏览器或者新建标签页都为空 | 5m左右 | 只能存储在浏览器端 | 不同tab之间无法共享 | 建议存储一些当前页面刷新需要存储,且不需要在tab关闭时候留下的信息,可根据这个来判断用户是否刷新进入,恢复音乐视频播放进度等 |
indexeddb | 永久保存,除非被清除 | 一个单独的数据库没有大小限制,不过可能限制每个Indexeddb数据库的大小,例如firefox在用户界面上只会针对存储超过 50 MB 大小的 BLOB(二进制大对象)请求权限,总体基本没有大小限制 | 只能存储在浏览器端 | 子域名之间相互独立 | 离线应用或webapp可以考虑使用indexeddb或者websql中存取数据 |
【tip】sessionStorage只能在一个标签页下共享,即如果你从当前标签页下新打开一个该网页的页面,sessionStorage数据也是清空的。不过如果你恢复关闭的页面的话,在chrome和firefox下sessionStorage也会被恢复,不过safari不会。
webStorage和indexeddb的兼容性
webStorage兼容性
Chrome | Firefox | IE | Opera | Safari | |
---|---|---|---|---|---|
localStorage | 4 | 3.5 | 8 | 10.50 | 4 |
sessionStorage | 5 | 2 | 8 | 10.50 | 4 |
基本浏览器都是支持的
indexeddb兼容性
Chrome | Firefox | IE | Opera | Safari | |
---|---|---|---|---|---|
l异步 API | 12 【webkit 】 | 16.0 (16.0) 4.0 (2.0)【 moz】 | 10 【ms】 | 未实现 | 未实现 |
同步 API | 未实现 | 未实现 | 未实现 | 未实现 | 未实现 |
目前兼容性较差
webStorage API
localStorage和sessionStorage的用法是一样的,下面展示sessionStorage的使用例子。
1 | // 保存数据到sessionStorage |
当然,你也可以直接用对象的赋值方式来设置
1 | sessionStorage['colorSetting'] = '#a4509b'; |
不过,官方建议只用webStorage API(getItem, removeItem, key, length),来避免使用对象键值存储的一些缺陷,缺陷详情请点击这里
storage事件
webStorage还有storage事件。当storage发生改变,storage事件就会被触发。
这里的的条件是数据发生了变化,如果当前的存储区域是空的,即使再调用clear()也不会触发事件。或者你通过setItem()来设置一个与现有值相同的值,事件也是不会触发的。
storage 属性
属性名 | 描述 |
---|---|
key | 代表属性名发生变化.当被clear()方法清除之后所有属性名变为null. Read only(只读). |
newValue | 新添加进的值.当被clear()方法执行过或者被属性名被删除,值会成为null Read only(只读). |
oldValue | 原始值.被clear()方法执行过则变为null,或者被新值取代。 Read only(只读). |
storageArea | 被操作的storage对象. Read only(只读). |
url | key发生改变的对象所对应的文档的URL地址.。 Read only(只读). |
下面介绍多标签页面使用sessionStorage时会有使用栗子。
多标签页面使用sessionStorage
在最近使用vuejs写完全前后端分离的项目时,在做登录认证的时候,在想到底怎么存储用户认证信息。
因为系统安全要求等级比较高,要求用户关闭标签页的时候会话立刻到期,使用cookie来保存敏感的token就不太合适了。如果使用localstorage,页面关闭后localstorage数据还在,也不太满足要求。
想着只能使用sessionStorage。
不过尴尬的是,使用sessionStorage是无法再多标签页面共享的。每次打开新标签页,就会跳转到登录页面,用户体验不太友好,查了一下资料,看到一博客是翻译了一外国小哥使用storage事件实现跨标签页共享sessionStorage的文章,学习了,点击这里看该博客。
简单来讲就是,如果新标签页如果没有sessionStorage数据,就会触发一个localstorage修改事件,那么在已存在的标签里收到这个事件后,就会将当前页的sessionStorage数据保存在localstorage中,但是马上移除。但是在新标签页里会监听到该事件,可以获取到这个sessionStorage数据,那这样就保证了新标签页也能获取sessionStorage,也保证localstorage中不存在token信息。
1 | (function() { |
IndexedDB
用法不像sessionStorage那么简单,不过以下两篇文章把基本indexeddb用法都讲的比较清楚了。就不额外做整理了。
【参考】
http://blog.kazaff.me/2016/09/09/译-在多个标签页之间共享sessionStorage/?utm_source=tuicool&utm_medium=referral
https://blog.guya.net/2015/06/12/sharing-sessionstorage-between-tabs-for-secure-multi-tab-authentication/
https://developer.mozilla.org/zh-CN/docs/Web/API/Window/sessionStorage
https://segmentfault.com/a/1190000005927232#articleHeader3