用户在一个标签页已登陆,再打开多个标签页,此场景下将token保存在sessionStorage中将会带来不好的用户体验,每次开启一个标签页都会要求用户从新登陆。html
sessionStorage顾名思义是针对一个session的数据存储,生命周期为当前窗口,一旦窗口关闭,那么存储的数据将被清空。最后还有一个很主要的区别同一浏览器的相同域名和端口的不一样页面间能够共享相同的 localStorage,可是不一样页面间没法共享sessionStorage的信息。浏览器
解决:
在index.html中增长如下代码,复制所有sessionStorage内资料安全
(function(){ // 判断当前页面是否存在sessionStorage if (!sessionStorage.length) { // 这个调用能触发目标事件,从而达到共享数据的目的(若不存在则加上一个localStorage Item,key=getSessionStorageData) localStorage.setItem('getSessionStorageData', Date.now()); }; // 该事件是核心,增长window监听事件 window.addEventListener('storage', function(event) { // 已存在的标签页会收到这个事件,若是监听到的事件key是getSessionStorageData if (event.key == 'getSessionStorageData') { // 再新增一个localStorage Item,key=sessionStorageData,value就是当前的sessionStorage localStorage.setItem('sessionStorage', JSON.stringify(window.sessionStorage)); // 删除localStorage中key=sessionStorageData的item localStorage.removeItem('sessionStorage'); } if (event.key == 'sessionStorageData' && !sessionStorage.length) { // 新开启的标签页会收到这个事件,把sessionStorageData的资料parse出来 const data = JSON.parse(event.newValue); // 赋值到当前页面的sessionStorage中 for (key in data) { window.sessionStorage.setItem(key, data[key]); } } }); })();
总体流程:
一、判断页面是否存在sessionStorage,并加上store事件的监听;
二、若不存在,就把本来的sessionStorage内的资料复制到localStorage中并取名为sessionStorageData;
三、若storage事件监听到key为sessionStorageData的事件,就把内容经过for赋值到页面sessionStorage中;session
为何复制到localStorage后又直接删除?
由于window添加了监听事件工具
window.addEventListener('storage', ..)
这就意味着每次storage事件被触发的时候都会执行,因此当setItem('sessionStorage')的时候,也会接收到事件,
表明着测试
window.localStorage.removeItem('sessionStorage')
实际上是发生在sessionStorage被写入以后的事情了,因此能够同时写入和删除,不留下localSorage的记录。code
新开的页面为何会有sessionStorage能够提供复制?
查询API(Using the Web Storage API|MDN)后知道,各标签只要是同域名,有对storage动做时所有都会被连动,storage事件能够作到同域名的状态监测。htm
storage事件的测试
随便开两个同域名的标签页后,分别开启开发者工具:
一、在A标签页下token
window.addEventListener('storage', (event) => console.log(event));
二、在B标签页下生命周期
window.localStorage.setItem('storageTest', 'test');
三、再回头看A标签页,就会发现已经被监听到storage事件了。
经过这样的事件监听,就能够达到由localSorage传递sessionStorage的目的。
关于登出
登出时同步清除全部标签页的sessionStorage并reload页面
(function(){ // 判断当前页面是否存在sessionStorage if (!sessionStorage.length) { // 这个调用能触发目标事件,从而达到共享数据的目的(若不存在则加上一个localStorage Item,key=getSessionStorageData) localStorage.setItem('getSessionStorageData', Date.now()); }; // 该事件是核心,增长window监听事件 window.addEventListener('storage', function(event) { // 已存在的标签页会收到这个事件,若是监听到的事件key是getSessionStorageData if (event.key == 'getSessionStorageData') { // 再新增一个localStorage Item,key=sessionStorageData,value就是当前的sessionStorage localStorage.setItem('sessionStorage', JSON.stringify(window.sessionStorage)); // 删除localStorage中key=sessionStorageData的item localStorage.removeItem('sessionStorage'); } if (event.key == 'sessionStorageData' && !sessionStorage.length) { // 新开启的标签页会收到这个事件,把sessionStorageData的资料parse出来 const data = JSON.parse(event.newValue); // 赋值到当前页面的sessionStorage中 for (key in data) { window.sessionStorage.setItem(key, data[key]); } } // ===== 加下面这段 ===== if (event.key === 'logout') { // 接收到logout事件,进行sessionStorage的清除和页面reload window.sessionStorage.clear(); window.location.clear(); } }); })();
其余即便这样看起来ok,但仍是有缺陷一、Chrome,FireFox的恢复分页功能会将sessionStorage的资料一块儿恢复,这可能会致使一些安全性问题(不过相较于localStorage,这应该不算问题)二、这些数据是标签页被开启的同时获取的,意味着若是你的sessionStorage储存着常常被变更的资料,必须再写一些事件去拦截和复制,由于storage事件不会监听到其余页面的sessionStorage变更.