zoukankan      html  css  js  c++  java
  • postMessage跨域实现localstorage跨域共享

    浅谈postMessage跨域通信与localStorage实现跨域共享

    我们可能有需要在多个域名之间共用同一个localStorage的需要

    一、我们先测试不同域名之间的通信

      1.有 child.html 如下,代码中 window.parent.postMessage(data,origin) 方法允许来自不同源的脚本采用异步方式进行通信,可以实现跨文本档、多窗口、跨域消息传递。接受两个参数:

    • data:要传递的数据,html5规范中提到该参数可以是JavaScript的任意基本类型或可复制的对象,然而并不是所有浏览器支持任意类型的参数,部分浏览器只能处理字符串参数,所以在传递参数时需要使用JSON.stringify()方法对对象参数序列化。
    • origin:字符串参数,指明目标窗口的源,协议+主机+端口号[+URL],URL会被忽略,所以可以不写,只是为了安全考虑,postMessage()方法只会将message传递给指定窗口,当然也可以将参数设置为"*",这样可以传递给任意窗口,如果要指定和当前窗口同源的话设置为"/"。
    复制代码
    <!doctype html>  
    <html>  
        <head>  
            <style type="text/css">  
                html,body{  
                    height:100%;  
                    margin:0px;  
                }  
            </style>  
        </head>  
        <body style="height:100%;">  
            <div id="container" onclick="changeColor();" style="widht:100%; height:100%; ">  
                click to change color  
            </div>  
            <script type="text/javascript">  
                var container = document.getElementById('container');  
                // iframe接收消息,并把当前颜色发送给主页面  
                changeColor();
                // 点击iframe时触发changeColor方法,把变化后的颜色发送给主页面  
                function changeColor() {       
                    var color = container.style.backgroundColor;  
                    if (color == 'rgb(204, 102, 0)')  
                        color = 'rgb(204, 204, 0)';  
                    else  
                        color = 'rgb(204,102,0)';  
                    container.style.backgroundColor = color;
                    console.log('start post color ..............');
                    window.parent.postMessage(color, '*');  
                }  
            </script>  
        </body>
    </html>
    复制代码

      2.然后在 main.html 中引入 child.html,window.addEventListener('message', function(e) { dosomething....}, false);  用来监听iframe 中发过来的消息

    复制代码
    <!DOCTYPE html>    
    <html>    
        <head>    
            <title></title>    
        </head>    
        <body>    
            <div style="200px; float:left; margin-right:200px;border:solid 1px #333;">    
                <div id="color">Frame Color</div>    
                </div>    
            <div>    
            <iframe id="child" src="http://www.abc.com/child.html"></iframe>    
            </div>    
            <script type="text/javascript">       
                // 主页面监听message事件,初始化自身颜色  
                // 主页面监听message事件,处理自身变色  
                window.addEventListener('message', function(e) {
                    console.log('listen.....');
                    var color = e.data;    
                    document.getElementById('color').style.backgroundColor = color;    
                }, false);    
            </script>    
        </body>    
    </html>  
    复制代码

      3.这时我们就可以看到效果了,如下图,当我们点击包含在main.html 中的 child.html页面时,main.html中的FrameColor也跟着变了

     二、接下来我们实现跨域之间的localstorage共享 

      1.解决思路:在A域和B域下引入C域,所有的读写都由C域来完成,本地数据存在C域下; 因此 A哉和B域的页面必定要引入C域的页面; 当然C域最好是主域,原因后面会提到(在localstorage 不方便的情况下使用cookie);

    • 【A域】【B域】需要读写时,通过postMessage 向【C域】发送跨哉消息,
    • 【C域】监听跨域消息,在接到批定的消息时进行读写操作,
    • 【C域】接到跨域消息时,如果是写入删除可以不做什么,如果是读取,就要先读取本域本地数据通过postMessage向父页面发送消息,
    • 【A 域 / B 域】在读取【C域】数据时就需要监听来自【C域】的跨域消息

      

      2.注意事项:

      window.postMessage()方法,向【C域】发消息,应用iframe.contentWindow.postMessage() 这样iframe内的【C 域】才可以接到,

      同理,【C域】向 【A 域B域】发消息时应用,window.parent.postMessage(),【A域、B域】的逻辑一定要在iframe 加载完成后进行。

      3.代码:

       【C域】页面如下:

    复制代码
    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <meta name="robots" content="noindex">
        <title>cross domain</title>
    </head>
    <body>
    <script>
      ;(function(doc,win,undefined){
          var fn=function(){};
          fn.prototype={
              /*本地数据存储*/
              setLocalCookie: function (k, v, t,domain) {
                  typeof window.localStorage !== "undefined" ? localStorage.setItem(k, v) :
                          (function () {
                              t = t || 365 * 12 * 60 * 60;
                              domain=domain?domain:".hc360.com";
                              document.cookie = k + "=" + v + ";max-age=" + t+";domain="+domain+";path=/";
                          })()
              },
              getLocalCookie: function (k) {
                  k = k || "localDataTemp";
                  return typeof window.localStorage !== "undefined" ? localStorage.getItem(k) :
                          (function () {
                              var all = document.cookie.split(";");
                              var cookieData = {};
                              for (var i = 0, l = all.length; i < l; i++) {
                                  var p = all[i].indexOf("=");
                                  var dataName = all[i].substring(0, p).replace(/^[suFEFFxA0]+|[suFEFFxA0]+$/g,"");
                                  cookieData[dataName] = all[i].substring(p + 1);
                              }
                              return cookieData[k]
                          })();
              },
              clearLocalData: function (k) {
                  k = k || "localDataTemp";
                  typeof window.localStorage !== "undefined" ? localStorage.removeItem(k) :
                          (function () {
                              document.cookie = k + "=temp" + ";max-age=0";
                          })()
              },
              init:function(){
                  this.bindEvent();
              },
              bindEvent:function(){
                  var _this=this;
                  win.addEventListener("message",function(evt){
                      if(win.parent!=evt.source){return}
                      var options=JSON.parse(evt.data);
                      if(options.type=="GET"){
                          var data=tools.getLocalCookie(options.key);
                          win.parent.postMessage(data, "*");
                      }
                      options.type=="SET"&&_this.setLocalCookie(options.key,options.value);
                      options.type=="REM"&&_this.clearLocalData(options.key);
                  },false)
              }
          };
          var tools=new fn();
          tools.init();
      })(document,window);
    </script>
    </body>
    </html>
    复制代码

      【A域】页面如下:我们再C中设置了 localStorage

    复制代码
    <!DOCTYPE html>    
    <html>    
        <head>    
            <title></title>    
        </head>    
        <body>    
            <div style="200px; float:left; margin-right:200px;border:solid 1px #333;">    
                <div id="color">Frame Color</div>    
                </div>    
            <div>    
            <iframe id="child" src="http:///c.html"></iframe>    
            </div>    
            <script type="text/javascript">   
                window.onload = function() {
                    console.log('set key value......................')
                    window.frames[0].postMessage(JSON.stringify({type:"SET",key:"key",value:"value"}),'*');
                }          
            </script>    
        </body>    
    </html>  
    复制代码

    上传A、C之后我们见到效果如上图

        【B域】页面如下:我们读取A中设置的 localStorage

    复制代码
    <!DOCTYPE html>    
    <html>    
        <head>    
            <title></title>    
        </head>    
        <body>    
            <div style="200px; float:left; margin-right:200px;border:solid 1px #333;">    
                <div id="color">Frame Color</div>    
                </div>    
            <div>    
            <iframe id="child" src="http:///c.html"></iframe>    
            </div>    
            <script type="text/javascript">   
                window.onload = function() {
                    console.log('get key value......................')
                    window.frames[0].postMessage(JSON.stringify({type:"GET",key:"key"}),'*');
                }
                window.addEventListener('message', function(e) {
                    console.log('listen.....');
                    var data = e.data;    
                    console.log(data);
                }, false);
            </script>    
        </body>    
    </html>  
    复制代码

    访问c打开console见到效果如下 

    至此我们实现了跨域 localStorage 的读取和删除。

  • 相关阅读:
    微信公众号 sign类
    serlvet HttpServletRequest
    servlet setCharacterEncoding setHeader 设置字符区别
    java 读取word
    java 使用Java生成word文档
    java io 读取写文件
    异步Promise及Async/Await可能最完整入门攻略
    React和Vue组件间数据传递demo
    Vue基础指令集锦
    vue 关于数组和对象的更新
  • 原文地址:https://www.cnblogs.com/lcosima/p/9543418.html
Copyright © 2011-2022 走看看