zoukankan      html  css  js  c++  java
  • Javascript 跨域

      JS跨域是指通过JS在不同的域之间进行数据传输或通信,比如用AJAX向一个不同的域请求数据,或者通过JS获取页面中不同域的框架中(iframe)的数据。只要协议、域名、端口有任何一个不同,都被当作是不同的域。

      不同环境下JS的通信:

    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://a.com/b.js

    同一域名,不同二级域名

    不允许

    http://www.cnblogs.com/a.js

    http://www.a.com/b.js

    不同域名

    不允许

      总结了一下,常见的跨域方法有一下几种:

    1、document.domain

    „对于主域相同而子域不同的例子,可以通过设置document.domain的办法来解决。

    „具体的做法是可以在http://www.a.com/a.html和http://script.a.com/b.html两个文件中分别加上document.domain = ‘a.com’;然后通过a.html文件中创建一个iframe,去控制iframe的contentDocument,这样两个js文件之间就可以“交互”了。

      http://www.a.com/a.html

    document.domain = 'a.com';
    
    var ifr = document.createElement('iframe');
    ifr.src = 'http://script.a.com/b.html';
    ifr.style.display = 'none';
    document.body.appendChild(ifr);
    
    ifr.onload = function(){
        var doc = ifr.contentDocument || ifr.contentWindow.document;
        // 在这里操纵b.html,调用函数使用ifr.contentWindow.funcName
        console.log(doc);
    };

      http://script.a.com/b.html

    document.domain = 'a.com';

    存在的问题:

      一、安全性,当一个站点(script.a.com)被攻击后,另一个站点(www.a.com)会引起安全漏洞。

        二、如果一个页面中引入多个iframe,要想能够操作所有iframe,必须都得设置相同domain。

    2、动态创建script

      虽然浏览器默认禁止了跨域访问,但并不禁止在页面中引用其他域的JS文件,并可以自由执行引入的JS文件中的function(包括操作cookie、Dom等等)。

    „  根据这一点,可以方便地通过创建script节点的方法来实现完全跨域的通信。
     
    3、JSONP(JSON with Padding)
    „  JSONP由两部分组成:回调函数和数据。回调函数是当响应到来时应该在页面中调用的函数,而数据就是传入回调函数中的JSON数据。
    „  在JS中,通过<script>可以在页面上引入不同域上的JS脚本文件,jsonp正是利用这个特性来实现的。
     
      前端:
    <script type="text/javascript">
    function dosomething(jsondata){
        //处理获得的json数据
    }
    </script>
    <script src="http://a.com/data.php?callback=dosomething">
    </script>

      服务器端:

    <?php
        $callback = $_GET['callback'];//得到回调函数名
        $data = array('a','b','c');//要返回的数据
        echo $callback.'('.json_encode($data).')';
        //输出dosomething(['a','b','c'])
    ?>

      JSONP by jQuery

    <script type="text/javascript">
    $.getJSON('http://a.com/data.php?callback=?',function(jsondata){
        //处理获得的json数据
    });
    </script>

    jquery会自动生成一个全局函数来替换callback=?中的问号,之后获取到数据后又会自动销毁,实际上就是起一个临时代理函数的作用。

    „$.getJSON方法会自动判断是否跨域,不跨域的话,就调用普通的ajax方法;跨域的话,则会以异步加载JS文件的形式来调用jsonp的回调函数
     
    JSONP的优点是:
      它不像XMLHttpRequest对象实现的Ajax请求那样受到同源策略的限制;它的兼容性更好,不需要XMLHttpRequest或ActiveX的支持。
    „JSONP的缺点则是:
    „  它只支持GET请求而不支持POST等其它类型的HTTP请求;
    „  它只支持跨域HTTP请求这种情况,不能解决不同域的两个页面之间如何进行JavaScript调用的问题。
     
    4、window.name
        „window对象有个name属性,该属性有个特征:即在一个窗口(window)的生命周期内,窗口载入的所有的页面都是共享一个window.name的。
    „  每个页面对window.name都有读写的权限,window.name是持久存在一个窗口载入过的所有页面中的,并不会因新页面的载入而进行重置。
      
    实现跨域需要3个文件:
      a.com/app.html:应用页面。
      a.com/proxy.html:代理文件,一般是一个没有任何内容的html文件,需要和应用页面在同一域下。
    „  b.com/data.html:应用页面需要获取数据的页面,可称为数据页面。
     
      a.com/app.html
    <iframe id="data" src="http://b.com/data.html" style="display:none;" onload="getData()">
    </iframe>
    <script>
        function getData() {
            var iframe = document.getElementById('data');
            iframe.onload = function () {
                var data = iframe.contentWindow.name;
                console.log(data);
            }
            iframe.src = 'http://a.com/proxy.html';
        }
    </script>

      b.com/data.html

    <script type="text/javascript">
        window.name = 'data'; 
        // 这里是要传输的数据,大小一般为2M,IE和firefox下可以大至32M左右
    </script>

    特点:

      „frame的src属性由外域转向本地域,跨域数据即由iframe的window.name从外域传递到本地域。巧妙地绕过了浏览器的跨域访问限制,但同时它又是安全操作。

    5、HTML5 window.postMessage

    „  window.postMessage(message,targetOrigin) 方法是html5新引进的特性,可以使用它来向其它的window对象发送消息,无论这个window对象是属于同源或不同源。
    „  目前IE8+、FireFox、Chrome、Opera等浏览器都已经支持window.postMessage方法。
     
    postMessage();
    otherWindow.postMessage(message, targetOrigin);
    
    //otherWindow: 对接收信息页面的window的引用。可以是页面中iframe的contentWindow属性;
    //message: 所要发送的数据,string类型。
    //targetOrigin: 用于限制otherWindow,“*”表示不作限制

      a.com/index.html

    <iframe id="ifr" src="b.com/index.html"></iframe>
    <script type="text/javascript">
        window.onload = function() {
        var ifr = document.getElementById('ifr');
        var targetOrigin = 'http://b.com'; 
        // 若写成'http://c.com'就不会执行postMessage了
        ifr.contentWindow.postMessage('I was there!', targetOrigin);
    };
    </script>

      b.com/index.html

    <script type="text/javascript">
        window.addEventListener('message', function(event){
            // 通过origin属性判断消息来源地址
            if (event.origin == 'http://a.com') {
                alert(event.data); // 弹出"I was there!"
                alert(event.source); // 对a.com、index.html中window对象的引用
                // 但由于同源策略,这里event.source不可以访问window对象
            }
        }, false);
    </script>

    6、跨域资源共享(CORS)

      „CORS(Cross-Origin Resource Sharing)跨域资源共享,定义了必须在访问跨域资源时,浏览器与服务器应该如何沟通。
    „  „CORS背后的基本思想就是使用自定义的HTTP头部让浏览器与服务器进行沟通,从而决定请求或响应是应该成功还是失败。
     
    跨域方法:
    <script type="text/javascript">
        var xhr = new XMLHttpRequest();
        xhr.open("GET", "http://b.com/new/",true);
        xhr.send();
    </script>

    注意:

    „  需要服务器和浏览器的支持
    „  例如PHP的响应页面顶端添加如下代码:
    header("Access-Control-Allow-Origin:http://a.com");
    „  表示接受来自a.com的跨域请求,"*"表示接受所有跨域请求
     
     
    总结不同跨域方法所使用的途径:

    跨域方法

    iframe

    script

    other

    window.domain

       

    动态<script>

     

     

    JSONP

     

     

    window.name

       

    window.postMessage

       

    CORS

       

    其他跨域方法:

    „  1. flash (YUI IO)
    „  2. 代理服务器
     
     
      
  • 相关阅读:
    PC-BSD 9.2 发布,基于 FreeBSD 9.2
    Attic 0.8.1 发布,备份程序
    Apache Lucene 4.5 发布,Java 搜索引擎
    Linux Kernel 3.11.4/3.10.15/3.4.65/3.0.99
    Lucene 查询工具 LQT
    Rubinius 2.0 发布,Ruby 虚拟机
    Golang通过Thrift框架完美实现跨语言调用
    微软再次要求Google审查官方链接 称将进行调查
    TCPDF 6.0.036 发布,PHP 的 PDF 操作包
    libnode 0.4.0 发布,C++ 语言版的 Node.js
  • 原文地址:https://www.cnblogs.com/dong93/p/4669965.html
Copyright © 2011-2022 走看看