zoukankan      html  css  js  c++  java
  • JavaScript跨域解决办法

    在找到跨域解决办法之前,我们要先弄清楚一些基本概念

    • 什么是跨域?
    • 什么是“同源策略”?
    • 跨文档消息通信 & 跨域请求数据
    • 主域相同而子域不同
    • 不同域名的跨域访问

    什么是跨域?

    简单地理解就是因为同源策略的限制,a.com 域名下的js无法操作b.com或是xx.a.com域名下的对象。那么什么是“同源策略”?
     

    什么是同源策略?

         源是在网络上用来建立信任关系的地址子集。源由规则(scheme)、主机(host)、端口(port)组成。例如,由于规则不同(如https与http),所以 http://www.a.com与 https://www.a.com页面的源是不同的。
    (有关这部分的内容,特别推荐Rain Man大哥写的这一篇,非常清晰易懂:http://www.cnblogs.com/rainman/archive/2011/02/20/1959325.html
     
         同源策略是指出于安全方面的考虑,运行在同一浏览器中的框架、标签页、窗口间的通信受到了严格的限制。源不同,则检索或修改其他源的内容时,浏览器会抛出安全异常,并阻止相应的操作。在html5 新的api出现以前,只有同源的页面才可以相互访问对象。 
     
    其实跨域通信是分为两部分来讲的:
    • 跨文档消息通信 (如读取不同源页面的DOM对象等)
    • 跨域请求数据(跨域ajax请求, jsonp请求等)
    注:实现跨域请求服务器数据 有很多种方式,如jsonp请求,flash等。本文主要讲“跨文档消息通信” 

    跨文档消息通信

           我们经常在工作中碰到的有两种:

    • 主域相同而子域不同

        可以通过设置document.domain+iframe的办法来解决 

    • 不同域名的跨域访问

             解决方案有很多,例如:

            1. iframe+代理页+hash的方式

            2. iframe + name

            3. postMessage 


    下面我们用个例子来实现 “跨文档消息通信”

    需求:a页面里有一个iframe(b页面)。当b页面加载完成后,同步一下iframe的高度。 

    1、“主域相同而子域不同” 的情况

         下次上代码

    2、“不同域名的跨域访问” 的情况

    iframe+代理页+hash的方式:利用proxy.html代理页来实现. 这个办法比较绕,但是可以解决完全跨域情况下的脚步置换问题。原理是利用location.hash来进行传值原理及流程。来张我画的草图:

    a页面,位于sport.taobao.com域名下 

     1 <!DOCTYPE html>
     2 <html>
     3 <head>
     4 <meta charset="gbk" />
     5 <script src="http://a.tbcdn.cn/s/kissy/1.3.0/kissy-min.js"></script>
     6 <style>
     7 body{background:#00ae8f;}
     8 .iframeArea{margin-top:30px;}
     9 </style>
    10 </head>
    11 <body>     
    12     A:运动页面 此页面访问时的url是这样的:
    13     http://sport.taobao.com/market/sports/a.php?iframeUrl=http://wanke.etao.com/mobile/product-600000000007215.html
    14     <div class="iframeArea">
    15         <iframe id="J_sport_iframe" name="sport_iframe" src="" frameborder="0" style="display: block; margin: 0 auto; height: 1000px;" width="990" scrolling="no" >
    16         </iframe>
    17     </div>
    18     <script>
    19         (function(S){
    20             KISSY.use('uri',function(S,Uri){
    21                 var url = new Uri(location.href).getQuery().get('iframeUrl');
    22                 if(url){
    23                     S.all('#J_sport_iframe').attr("src",url);    //给iframe赋src的值
    24                 }else{
    25                     S.all('#J_sport_iframe').attr("src","http://wanke.etao.com/error.html");
    26                 }
    27             });
    28         })(KISSY);
    29     </script>
    30 </body>
    31 </html>
    View Code

    b页面位于wanke.etao.com域名下

    <!DOCTYPE html>
    <html>
    <head>
    <meta charset="gbk" />
    <script src="http://a.tbcdn.cn/s/kissy/1.3.0/kissy-min.js"></script>
    </head>
    <body>     
    <div>
    我是玩客页面:http://wanke.etao.com/mobile/product-600000000007215.html
    </div>   
    <script>
        /*
       etao的B.html js 写在页面结束时
       */
      (function (S) {
        if (window != top) {
            //在etao的页面B.html中创建iframe代理
            S.one('body').append('<iframe id="iframeproxy" name="iframeproxy" src="" width="0" height="0" style="display:none;" ></iframe>');
            
            function updateHeight() {
                if (window !=top && S.one("#iframeproxy")) {
                    var ht = S.one("body").height() + 10, a = window.name, b;
                    b = "http://sport.taobao.com/market/sports/iframe-proxy2.php"
                    S.one("#iframeproxy")[0].src = b + "#" + ht;
                }
            }
            updateHeight();
            S.one(window).on('load', function () {
                updateHeight();
            });
        }
    })(KISSY); 
    </script>
    </body>
    </html>
    View Code

    proxy页面位于sport.taobao.com域名下,但是插入到b页面中

     1 <!DOCTYPE html>
     2 <html>
     3 <head>
     4 <meta charset="gbk" />
     5 <script src="http://a.tbcdn.cn/s/kissy/1.3.0/kissy-min.js"></script>
     6 </head>
     7 <body>     
     8     <script>
     9     /*
    10     taobao站点页面中的js http://sport.taobao.com/market/baobao/iframe-proxy2.php
    11     */
    12     (function(S){        
    13         function pseth() {
    14           var iObj = window.top.document.getElementById('J_sport_iframe');//A和iframe-proxy2同域,所以可以访问节点
    15           iObjH = window.location.hash;//访问自己的location对象获取hash值
    16           iObj.style.height = (+iObjH.split("#")[1]+5)+"px";//操作dom
    17         }
    18         pseth();
    19         S.all(window).on("hashchange",function(){
    20             pseth();
    21         });
    22 
    23     })(KISSY);
    24     </script>
    25 </body>
    26 </html>
    View Code

    3. postMessage

      我这里有篇文章专门写postMessage做跨域的。请看 http://www.cnblogs.com/summer_shao/p/3998695.html

  • 相关阅读:
    LeetCode 295. Find Median from Data Stream (堆)
    LeetCode 292. Nim Game(博弈论)
    《JavaScript 模式》读书笔记(4)— 函数2
    《JavaScript 模式》读书笔记(4)— 函数1
    《JavaScript 模式》读书笔记(3)— 字面量和构造函数3
    《JavaScript 模式》读书笔记(3)— 字面量和构造函数2
    《JavaScript 模式》读书笔记(3)— 字面量和构造函数1
    《JavaScript 模式》读书笔记(2)— 基本技巧3
    《JavaScript 模式》读书笔记(2)— 基本技巧2
    《JavaScript 模式》读书笔记(2)— 基本技巧1
  • 原文地址:https://www.cnblogs.com/summer_shao/p/proxy.html
Copyright © 2011-2022 走看看