赞
踩
html5标准中一个亮点就是提供了浏览器本地存储的功能。方式有两种:localStorage和 sessionStorage。 相对于cookie,他们具有存储空间大的特点,一般可以存储5M左右,而cookie一般只有4k。
localStorage和 sessionStorage的主要区别是:localStorage的生命周期是永久的,意思就是如果不主动清除,存储的数据将一直被保存。而sessionStorage顾名思义是针对一个session的数据存储,生命周期为当前窗口,一旦窗口关闭,那么存储的数据将被清空。
当然作为孪生兄弟,两者也有很多相同点。比如存取数据的方法就是一样的。
#localStorage和sessionStorage的一些方法: #添加键值对: setItem(key,value); #获取键值对: getItem(key); #删除键值对: removeItem(key); #清除所有键值对: clear(); #获取属性名称(键名称): key(index); #获取键值对的数量: length; #localStorage 的存取方式 localStorage.age = 88; // 用localStorage属性的方式来添加条目 localStorage.setItem("animal","cat"); // 推荐使用setItem的方式存储一个名为animal,值为cat的数据 var animal = localStorage.getItem("animal"); //读取本地存储中名为animal的数据,并赋值给变量animal console.log(animal); localStorage.removeItem("animal"); //删除单条数据 localStorage.clear(); //清除所有数据 #sessionStorage 的存取方式 sessionStorage.work = "police"; sessionStorage.setItem("person", "Li Lei"); var person = sessionStorage.getItem("person"); console.log(person);
另外,不同浏览器无法共享localStorage和sessionStorage中的信息。同一浏览器的相同域名和端口的不同页面间可以共享相同的 localStorage,但是不同页面间无法共享sessionStorage的信息。这里需要注意的是,页面仅指顶级窗口,如果一个页面包含多个iframe且他们属于同源页面,那么他们之间是可以共享sessionStorage的。在实际开发过程中,遇到的最多的问题就是localStorage的同源策略问题。为了了解这个问题,我们先得清楚什么是同源策略。同源策略(same-origin policy)是浏览器执行的一种安全措施,目的是为了保证用户信息的安全,防止恶意的网站窃取数据。浏览器的同源策略具体如下:
URL 说明 是否允许通信
http://www.a.com/a.js http://www.a.com/b.js 同一域名下 允许 http://www.a.com/lab/a.js http://www.a.com/script/b.js 同一域名下不同文件夹 允许 http://www.a.com:8000/a.js http://www.a.com/b.js 同一域名,不同端口 不允许 http://www.a.com/a.js https://www.a.com/b.js 同一域名,不同协议 不允许 http://www.a.com/a.js http://70.32.92.74/b.js 域名和域名对应ip 不允许 http://www.a.com/a.js http://script.a.com/b.js 主域相同,子域不同 不允许 http://www.a.com/a.js http://file.a.com/b.js 同一域名,不同二级域名(同上) 不允许(cookie这种情况下也不允许访问) http://www.cnblogs.com/a.js http://www.a.com/b.js 不同域名 不允许
只要不同源就不能共享localStorage的数据。但是在实际开发中又时常会遇到这样的需求,那我们该如何解决呢?
目前广泛采用的是postMessage和iframe相结合的方法。postMessage(data,origin)方法允许来自不同源的脚本采用异步方式进行通信,可以实现跨文本档、多窗口、跨域消息传递。接受两个参数:
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>cross domain</title> </head> <body> <h2>Status</h2> <p></p> <a href="http://www.test2.com/index_b.html">去index_b查看结果</a> <iframe src="http://www.test2.com/getmessage.html" frameborder="0"></iframe> <script> window.onload = function(){ //在页面加载完成后主页面向iframe发送请求 window.frames[0].postMessage('jogging, reading and writing','http://www.test2.com'); } // 主页面监听message事件, window.addEventListener('message', function(e){ var data = e.data; document.querySelector('p').innerHTML = data; }, false); </script> </body> </html>
http://www.test2.com/getmessage.html
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>getmessage</title> </head> <body> <script> //iframe接收消息,并把当前颜色发送给主页面 window.addEventListener('message', function(e) { if (e.source != window.parent) return; console.log(e.data); localStorage.setItem('task',e.data); window.parent.postMessage('finished', '*'); }, false); </script> </body> </html>
http://www.test2.com/index_b.html
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Document</title> </head> <body> <div>点击获取任务</div> <p></p> <script> document.querySelector('div').addEventListener('click', function(){ document.querySelector('p').innerHTML = localStorage.getItem('task'); }, false); </script> </body> </html>
以上示例中,很好的实现了localStorage的跨域存储功能。这样就算解决问题了吗?
我们还会遇到另一个棘手的问题。在safari浏览器下,这种方法就不可行了。由于safari浏览器的默认限制,父页面无法向iframe里的跨域页面传递信息。这时针对safari浏览器就得另辟蹊径了。本人在项目中用的方法是在safari浏览器下,用url传值的方法来实现跨域存储功能。用这种方法有一个问题必须要先考虑的,就是safari浏览器的url能够支持多长的字符呢? url的长度极限是由两方面决定的,一个是浏览器本身的限制,另一个就是服务器的限制。有人在Apache 2.4服务器上设置了一个非常大的LimitRequestLine 和 LimitRequestFieldSize,然后进行测试,结果表明safari浏览器可以支持超过64k个字符的长度。一般服务器默认支持2~3万个字符长度的url不成问题。所以只要需要传输的数据量不是非常大的话,可以直接通过url来进行传递,如此就能解决safari下的跨域存储问题。示例如下:
http://www.test.com/index_a.html
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>cross domain</title> </head> <body> <h2>Status</h2> <p></p> <a href="http://www.test2.com/index_b.html">去index_b查看结果</a> <iframe src="http://www.test2.com/getmessage.html" frameborder="0"></iframe> <script> var isSafari = navigator.userAgent.indexOf("Safari") > -1 && navigator.userAgent.indexOf("Chrome") < 0; window.onload = function(){ if(isSafari){ var aobj = document.querySelector('a'); var href = 'http://www.test2.com/index_b.html?message='+ encodeURIComponent('jogging, reading and writing'); aobj.setAttribute('href', href); }else{ //在页面加载完成后主页面向iframe发送请求 window.frames[0].postMessage('jogging, reading and writing','http://127.0.0.1:8082'); } } // 主页面监听message事件, window.addEventListener('message', function(e){ var data = e.data; document.querySelector('p').innerHTML = data; }, false); </script> </body> </html>
http://www.test2.com/index_b.html
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Document</title> </head> <body> <div>点击获取任务</div> <p></p> <script> var isSafari = navigator.userAgent.indexOf("Safari") > -1 && navigator.userAgent.indexOf("Chrome") < 0 ; function GetQueryString(name) { var reg = new RegExp("(^|&)"+ name +"=([^&]*)(&|$)"); var r = window.location.search.substr(1).match(reg); if(r!=null)return decodeURIComponent(r[2]); return null; } if(isSafari){ var data = GetQueryString('message'); localStorage.setItem('task',data); } document.querySelector('div').addEventListener('click', function(){ document.querySelector('p').innerHTML = localStorage.getItem('task'); }, false); </script> </body> </html>
如此就可以比较好的解决localStorage的跨域存储问题了。
实际开发需求: A域名网页 --> B域名网页传值
解决方案: window.postMessage 和 iframe相结合的方法
window.postMessage(message, targetOrigin)
message: 将要发送到其他 window的数据,在传递参数时需要使用JSON.stringify()方法对参数序列化
targetOrigin:指定哪些窗口能接收到消息事件,其值可以是字符串""(表示无限制)或者一个URI。在发送消息的时候,如果目标窗口的协议、主机地址或端口这三者的任意一项不匹配targetOrigin提供的值,那么消息就不会被发送;只有三者完全匹配,消息才会被发送。这个机制用来控制消息可以发送到哪些窗口; 例如,当用postMessage传送密码时,这个参数就显得尤为重要,必须保证它的值与这条包含密码的信息的预期接受者的origin属性完全一致,来防止密码被恶意的第三方截获。如果你明确的知道消息应该发送到哪个窗口,那么请始终提供一个有确切值的targetOrigin,而不是。不提供确切的目标将导致数据泄露到任何对数据感兴趣的恶意站点。
具体示例:
1、A域名页面 http://www.AAAA.com/a_Page.html 【设置A域名下 localStorage值,并向B域名发送数据】
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>cross domain</title> </head> <body> <div>A域名页面存储localStorage值</div> <script> let Aval = { name: 'Apage', size: 100 }; localStorage.setItem('setVal',JSON.stringify(Aval)); window.parent.postMessage(localStorage.getItem('setVal'), 'http://www.BBBB.com'); </script> <script src="https://cdn.bootcss.com/eruda/1.3.1/eruda.js"></script> <script>eruda.init();</script> </body> </html>
2、B域名页面 http://www.BBBB.com/b_Page.html 【获取A域名下 localStorage值】
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>cross domain</title> <script> window.addEventListener('message', function(e) { if (e.data) document.getElementById('app').innerHTML = e.data; }); </script> </head> <body> <div>获取A域名页面存储下来的localStorage值</div> <div id="app"></div> <iframe src="http://www.AAAA.com/a_Page"></iframe> </body> </html>
备注:
1、不同浏览器无法共享localStorage和sessionStorage中的信息。同一浏览器的相同域名和端口的不同页面间可以共享相同的
localStorage,但是不同页面间无法共享sessionStorage的信息。
这里需要注意的是,页面仅指顶级窗口,如果一个页面包含多个iframe且他们属于同源页面,那么他们之间是可以共享sessionStorage的
2、客户端APP内不同的webview不能共享localStorage和sessionStorage中的信息(eg:App和内置的SDK之间环境隔离)
————————————————
版权声明:本文为CSDN博主「飞扬_柳絮」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/tjcjava/article/details/113742318
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。