跨域

作者: 海子小夜曲 | 来源:发表于2018-12-11 19:45 被阅读0次

    CORS的使用

    CORS要前后端同时做配置。

    1、首先我们来看前端。

    纯js的ajax请求。

    <script type="text/javascript">

        var xhr = new XMLHttpRequest(); //ie6以下用new ActiveXObject("Microsoft.XMLHTTP");可以做能力判断。

        xhr.open(" GET", "/haorooms",true);

        xhr.send();

    </script>

    以上的haorooms是相对路径,如果我们要使用CORS,相关Ajax代码可能如下所示:

    <script type="text/javascript">

        var xhr = new XMLHttpRequest();//ie6以下用new ActiveXObject("Microsoft.XMLHTTP");可以做能力判断。

        xhr.open(" GET", "http://www.haorooms.com/CORS",true);

        xhr.send();

    </script>

    当然,你也可以用jquery的ajax进行。

    2、后端或者服务器端的配置

    下面我们主要介绍Apache和PHP里的设置方法。

    Apache:Apache需要使用mod_headers模块来激活HTTP头的设置,它默认是激活的。你只需要在Apache配置文件的 < Directory >, < Location>, < Files >或< VirtualHost>的配置里加入以下内容即可:

    Header set Access-Control-Allow-Origin * 

    PHP:只需要使用如下的代码设置即可。

    <?php 

    header("Access-Control-Allow-Origin:*"); 

    以上的配置的含义是允许任何域发起的请求都可以获取当前服务器的数据。当然,这样有很大的危险性,恶意站点可能通过XSS攻击我们的服务器。所以我们应该尽量有针对性的对限制安全的来源,例如下面的设置使得只有www.haorooms.com这个域才能跨域访问服务器的API。

    Access-Control-Allow-Origin: http://www.haorooms.com

    来自 <http://www.haorooms.com/post/js_kuayu_service>

    通过jsonp跨域

    jsonp跨域也需要前后端配合使用。一般后端设置callback ,前端给后台接口中传一个callback 就可以。

    例如前端代码:

    <script type="text/javascript">

        function dosomething(jsondata){

            //处理获得的json数据

        }

    </script>

    <script src="http://haorooms.com/data.php?callback=dosomething"></script>

    后台代码:

    <?php

    $callback = $_GET['callback'];//得到回调函数名

    $data = array('a','b','c');//要返回的数据

    echo $callback.'('.json_encode($data).')';//输出

    ?>

    假如你用ajax方式进行jsonp跨域,我之前的一篇文章中提及过:http://www.haorooms.com/post/jquery_ajax_wg

    /* 

    //简写形式,效果相同 

    $.getJSON("url跨域地址",  {参数,要把callback作为参数传到后端},

            function(data){ 

                //结构处理

    },"jsonp"); 

    */ 

    $.ajax({ 

        type : "get", 

        url : "跨域地址", 

        dataType : "jsonp",//数据类型为jsonp 

        jsonp: "callback",//服务端用于接收callback调用的function名的参数【后台接受什么参数,我们就传什么参数】我们上面设置是callback

        success : function(data){ 

            //结果处理

        }, 

        error:function(data){ 

              console.log(data);

        } 

    });

    来自 <http://www.haorooms.com/post/js_kuayu_service>

    通过修改document.domain来跨子域

    我们只需要在跨域的两个页面中设置document.domain就可以了。修改document.domain的方法只适用于不同子域的框架间的交互。

    例如:1.在页面 http:// www.haorooms.com/a.html 中设置document.domain

    <iframe id = "iframe" src="http://haorooms.com/b.html" onload = "test()"></iframe>

    <script type="text/javascript">

        document.domain = 'haorooms.com';//设置成主域

        function test(){

            alert(document.getElementById(' iframe').contentWindow);//contentWindow 可取得子窗口的 window 对象

        }

    </script>

    2、在页面http:// haorooms.com/b.html 中设置document.domain

    <script type="text/javascript">

        document.domain = 'haorooms.com';//在iframe载入这个页面也设置document.domain,使之与主页面的document.domain相同

    </script>

    来自 <http://www.haorooms.com/post/js_kuayu_service>

    使用window.name来进行跨域

    原理:

    window对象有个name属性,该属性有个特征:即在一个窗口(window)的生命周期内,窗口载入的所有的页面都是共享一个window.name的,每个页面对window.name都有读写的权限,window.name是持久存在一个窗口载入过的所有页面中的。

    方法:

    假如有三个页面。

    a.com/app.html:应用页面。

    a.com/proxy.html:代理文件,一般是一个没有任何内容的html文件,需要和应用页面在同一域下。

    b.com/data.html:应用页面需要获取数据的页面,可称为数据页面。

    1、在应用页面(a.com/app.html)中创建一个iframe,把其src指向数据页面(b.com/data.html)。

    数据页面会把数据附加到这个iframe的window.name上,data.html代码如下:

    <script type="text/javascript">

        window.name = 'I was there!';    // 这里是要传输的数据,大小一般为2M,IE和firefox下可以大至32M左右

                                        // 数据格式可以自定义,如json、字符串

    </script>

    2、在应用页面(a.com/app.html)中监听iframe的onload事件,在此事件中设置这个iframe的src指向本地域的代理文件(代理文件和应用页面在同一域下,所以可以相互通信)。

    app.html部分代码如下:

    <script type="text/javascript">

        var state = 0,

        iframe = document.createElement('iframe'),

        loadfn = function() {

            if (state === 1) {

                var data = iframe.contentWindow.name;    // 读取数据

                alert(data);    //弹出'I was there!'

            } else if (state === 0) {

                state = 1;

                iframe.contentWindow.location = "http://a.com/proxy.html";    // 设置的代理文件

            } 

        };

        iframe.src = 'http://b.com/data.html';

        if (iframe.attachEvent) {

            iframe.attachEvent('onload', loadfn);

        } else {

            iframe.onload  = loadfn;

        }

        document.body.appendChild(iframe);

    </script>

    3、获取数据以后销毁这个iframe,释放内存;这也保证了安全(不被其他域frame js访问)。

    <script type="text/javascript">

        iframe.contentWindow.document.write('');

        iframe.contentWindow.close();

        document.body.removeChild(iframe);

    </script>

    来自 <http://www.haorooms.com/post/js_kuayu_service>

    相关文章

      网友评论

          本文标题:跨域

          本文链接:https://www.haomeiwen.com/subject/yroehqtx.html