• 跨域通信——多窗口通信


    一、什么是跨域?
    一般来说,向一个非同源网站发送请求获取数据,就是跨域请求。
    //跨域错误提示
    Failed to load http://luna.58.com/api/getcity: No 'Access-Control-Allow-Origin' header is present on the requested resource. Origin 'http://localhost:63342'; is therefore not allowed access.
     
    同源策略——跨域问题产生原因
    浏览器为了网络信息安全所采取的的措施,限制资源访问权限。
    来源相同是指:协议、主机(域名),端口号,全部相同。
    http://www.example.com/dir/page.html
     
    协议:http
    域名:www.example.com
    端口:80(默认端口,可以省略)
     
    • http://www.example.com/dir2/other.html:同源
    • http://example.com/dir/other.html:不同源(域名不同)(域名必须完全相同)
    • http://www.example.com:81/dir/other.html:不同源(端口不同)
     
    域名级别
    一级域名(顶级域名):baidu.com
    二级域名:www.baidu.com
    三级域名:wangshangyingxiao.club.1688.com
     
    同源策略限制范围
    //如果非同源,共有三种行为受到限制
    (1)cookie、localstorage、IndexDB 无法读取
    (2)DOM结构无法获得
    (3)AJAX请求不能发送
     
     
    二、跨域通信方法
     
    1、设置document.domain
    此方法只适用于:两个网页一级域名相同,二级域名不同(或者三级域名不同)
    (1)共享cookie;(2)iframe窗口,获取dom结构。
    实现方法:两个网页设置相同的document.domain,设置为一级域名,即可共享cookie
     
    情景1:实现cookie共享,两个网页一级域名相同,二级域名不同。
    cookie是服务器写入浏览器的信息,只有同源的网页才可以共享。
     
    //举例说明:
    A网页:http://w1.example.com/a.html 默认 document.domain 值为 w1.example.com
    B网页:http://w2.example.com/b.html默认 document.domain 值为 w2.example.com
     
    //设置相同的domain
    document.domain = 'example.com';
     
    //设置后
    docoment.domain //两个页面的值均为 example.com
     
    //A页面,设置cookie
    document.cookie = 'test=hello';
     
    //B页面,获取cookie
    document.cookie //cookie的值中包含设置的test=hell
     
    服务器也可以在设置cookie时,指定cookie的所属域名为一级域名, 这样的话,二级域名和三级域名不用做任何设置,都可以读取到这个cookie。
     
    情景2:获取iframe的Dom结构,两个网页一级域名相同,二级域名不同。
    iframe Dom结构:只有同源的页面才可以相互通信,获取DOM结构。
    //举例说明:
    父窗口:http://w1.example.com/a.html 默认 document.domain 值为 w1.example.com
    子窗口iframe(#myIframe)http://w2.example.com/b.html默认 document.domain 值为w2.example.com
     
    //设置前,非同源页面,父窗口获取子窗口dom,报错
    document.getElementById('#myIframe').contentWindow.document
    //Uncaught DOMException: Blocked a frame from accessing a cross-origin frame.
     
    //设置前,非同源页面,窗口获取父窗口dom,报错
    window.parent.document.body
    //Uncaught DOMException: Blocked a frame from accessing a cross-origin frame.
     
    //设置相同的domain
    document.domain = 'example.com';
     
    //设置后,即可获取Dom
    docoment.domain //两个页面的值均为 example.com
     
    2、片段识别符 (fragment identifier)
    针对完全不同源的主页面与iframe页面,解决跨域通信的问题。将通信内容写入片段标识符中。
    片段识别符是指URL中#号后面的部分,例如:http://example.com/x.html#fragment的#fragment。
    只更改片段标识符,页面不会重新刷新。
    缺点:片段标识符中数据长度受限
    //父窗口将信息,写入子窗口的片段标识符
    var iframeEle = document.getElementById('iframe');
    console.log("父页面:" + location.href);
    // console.log("父页面获取子页面url:" + iframeEle.contentWindow.location.href);//报错,跨域
     
    /*片段标识符跨域*/
    iframeEle.src = iframeEle.src + '#faterData';
    window.onhashchange = function(){
    console.log('父窗口hash变化:' + window.location.hash);
    }
     
    //子窗口监听hashchange事件得到通知
    console.log("子页面:" + location.href);
    // console.log("子页面获取父页面url:" + top.location.href);//报错,跨域
     
    /*片段标识符跨域*/
    window.onhashchange = function(){
    console.log('子窗口hash变化:' + window.location.hash);
    };
    top.location.href = "http://localhost:63342/luna_gather/src/index_test.html#childData3";;
    // top.location.href = top.location.href + "#childData2"; ////报错,跨域
     
    3.window.name
    浏览器窗口有window.name属性,这个属性的特点是:只要在同一窗口中,无论是否同源,不同网页的window.name属性都是共享的。
    优点:window.name数据容量大(相比片段识别符)
    缺点:(1)必须同一窗口;(2)必须监听窗口window.name属性的变化,影响网页性能;
     
    4.postMessage
    可以实现完全不同源的窗口进行有限的通信。
    语法:
    (1)发送方发送消息
    otherWindow.postMessage(message,targetOrigin,[transfer]);
    ①otherWindow:其他窗口的引用,如(1)iframeEle.contentWindow;(2)window.open返回的窗口对象;(3)命名过或数值索引的window.frames,如window.frames[0]
    ②message:传送数据
    ③targetOrigin:指定接受数据的窗口的源,可以为特定url,或者“*”,表示全部窗口
    ④transfer:是一串和message同时传递的Transferable对象,这些对象的所有权将被转移给消息的接收方,而发送方将不再保留所有权。
     
    (2)接收方,监听message事件,接收消息
    window.addEventListener('message',function(event){});
    messageEvent涉及到以下四个属性:
    ①type:message的类型
    ②data:postMessage发送过来的数据
    ③origin:调用postMessage方法的窗口的源,即发送消息的窗口的源
    ④source:调用postMessage方法的窗口对象
     
    (3)案例演示
    父页面:http://a.com/main.html
    <!DOCTYPE html>
    <html lang="en">
    <head>
    <meta charset="UTF-8">
    <title>Title</title>
    </head>
    <body>
    <iframe id="iframe" src="http://b.com/iframe.html" frameborder="0"></iframe>
    </body>
    <script type="text/javascript">
    window.onload = function(){
    var iframeEle = document.getElementById('iframe');
    console.log("父页面:" + location.href);
    // console.log("父页面获取子页面url:" + iframeEle.contentWindow.location.href);//报错,跨域
     
    /*postMessage跨域*/
    window.frames[0].postMessage("我是父页面", '*');//第一种方式
    iframeEle.contentWindow.postMessage("我是父页面2", 'http://b.com/';);//第二种方式
    window.addEventListener('message',function(e){
    console.log("父窗口接受数据:" + e.data);
    });
     
    }
     
    </script>
    </html>
     
    子页面:http://b.com/iframe.html
    <!DOCTYPE html>
    <html lang="en">
    <head>
    <meta charset="UTF-8">
    <title>Title</title>
    </head>
    <body>
    <iframe id="iframe" src="http://b.com/iframe.html"; frameborder="0">
    </iframe>
    </body>
    <script type="text/javascript">
    window.onload = function(){
    console.log("子页面:" + location.href);
    // console.log("子页面获取父页面url:" + top.location.href);//报错,跨域
     
    /*postMessage跨域*/
    top.postMessage('我是子页面','http://a.com/main.html');
    window.addEventListener('message',function(e){
     
    console.log('子窗口接受数据:' + e.data);
    e.source.postMessage('我接受到数据了','*');
    },false);
     
    }
     
    </script>
    </html>
     
    注意:postMessage一定要在页面完成加载之后执行(即onload之后),否则会报错:
    Failed to execute ‘postMessage’ on ‘DOMWindow’
     
    可以利用postMessage,实现跨域窗口的localstorage操作。
     
    5、AJAX
     
    同源政策限制,AJAX请求只能发给同源网址,否则跨域报错。
    除了架设服务器代理外,(即浏览器请求同源服务器,再由后者请求外部服务器),有三种方法规避同源限制
    1、JSONP
    2、WebSocket
    3、CORS
     
    具体内容,之后单独列出。
     
  • 相关阅读:
    python 多线程实例
    手把手教你做酷炫的数据可视化大屏,零基础的你仅需6步
    化繁为简:数据库运维人员应该知道这些...
    凭什么它能成为报表神器?这五大技术硬货不得不服
    《算法图解》学习笔记(九):动态规划(附代码)
    前端布局总结(持续更新)
    前端布局总结(持续更新)
    前端布局总结(持续更新)
    前端布局总结(持续更新)
    linux之centos安装jdk以及nginx详细过程
  • 原文地址:https://www.cnblogs.com/zuozuo-blog/p/9391230.html
Copyright © 2020-2023  润新知