美文网首页
同源策略及跨域

同源策略及跨域

作者: Hunter_Gu | 来源:发表于2016-12-17 21:05 被阅读14次

    以a.com 和 child.a.com
    a.com 和 b.com
    为例
    先修改本地hosts文件,便于验证


    • 引用

    • 1.实现a.com 引用 child.a.com 下的main.js文件(本来就无限制)
      a.html中

    <script type="text/javascript" src="//child.a.com/test/origin/main.js"></script>
    
    • 2.a.html通过main.js文件读取child.a.com下的data(内容假设为1)文件内的内容
      main.js中:
    $.get('//child.a.com/test/origin/data',function(response){
       console.log(response)
    });
    

    a.com中会报错


    child.a.com中正常工作


    • 降域
    • 1.在a.com的html中添加
    <iframe src="//child.a.com/test/origin/child.html"></iframe>
    
    • 2.document.domain = 'a.com'在 a.com 和 child.a.com 中添加
    <script type="text/javascript">
       document.domain = 'a.com';
    </script>
    

    这样就可以改变两者的域名为'a.com',这样两者就同名了

    • 3.在child.a.com中设置window.name
    <script type="text/javascript">
       document.domain = 'a.com';
       window.name='child';
    </script>
    
    • 4.在a.com中进行访问
    <script type="text/javascript">
           document.domain = 'a.com';
           setTimeout(function(){
               console.log(window.frames[0].window.name);
           },2000);//等待iframe加载完,否则报错
    </script>
    

    即 a.com 可以对 child.a.com中的JS进行操作,甚至可以在 a.com 中调用 child.a.com 的JS中的方法。
    child.a.com中定义方法,最好以window对象的方式定义

    window.functionChild = function(){
        console.log('child.a.com');
    }
    

    a.com中调用该方法

    window.frames[0].functionChild();
    

    缺点:

    • 只对iframe形式的页面有效。

    • 只对拥有相同一级域名的情况有效。(child.a.com 和 a.com有相同的一级域名(a.com)),所以 a.com 和 b.com 不能通过降域来实现跨域。

    • JSONP(以a.com 访问 b.com的后台php文件为例)

    • 1.在 a.com 中️

    <script type="text/javascript">
       function foo(data){
           console.log(data);
       }
    </script>
    <script type="text/javascript">
       var script = document.createElement('script');
       script.src = '//b.com/test/origin/b.php?callback=foo';/*后台的php中可以GET到($_GET["callback"])*/
       $('body').append(script);
    </script>
    
    • 2.在 b.com 的 后台 b.php 文件中️
    <?php
       $data = $_GET['callback'];
    
       echo $data . '({"name": "Hunter","age":"22"})';/*模仿后台从数据库中得到的数据*/
    ?>
    

    此时a.com的 JS文件会收到foo({"name": "Hunter","age":"22"}),所以a.com的JS文件中的foo()函数就可以执行。
    所以 a.com 实现了对 b.com 下的数据库进行读的操作。


    JSONP的缺点:

    • 1.安全问题:任何网页只要复制JSONP的代码后,都可以实现跨域。(解决方法,附加一个动态参数,用于验证)
    script type="text/javascript">
        var script = document.createElement('script');
        var cookie=...;/*动态获取的当前登录的cookie,其他网页无法获取该信息*/
        script.src = '//b.com/test/origin/b.php?callback=foo&token=cookie';/*另一端进行验证*/
        $('body').append(script);
     </script>
    
    • 2.不能用POST请求(即只能进行读操作),只能通过GET请求(script标签只能触发GET请求,又GET方式写数据比较危险)
    • 3.可能会被恶意注入信息(可以通过字符串过滤避免)
    var script = document.createElement('script');
        script.src = '//b.com/test/origin/b.php?callback=alert(...)';/*另一端进行验证*/
        $('body').append(script);
    
    • CORS(跨域资源共享)
      以 a.com 访问 b.com的后台b.php文件为例
      在 b.com的后台 b.php文件中
    header("Access-Control-Allow-Origin:http://a.com");/*设置响应头后,a.com就可以访问b.com的资源了*/
        $name = $_POST["name"];
        $age = $_POST["age"];
        $ret = array($name,$age);
    
        echo  json_encode($ret);
    

    设置完响应头后,a.com直接发起Ajax请求即可。

    $.ajax({
       type: "POST",
       url: "//b.com/test/origin/b.php",
       data: {
        "name": "Hunter",
        "age": "22"
       },
       dataType: "json",
       success: function(msg){
         console.log(msg);
       }
    });
    

    相关文章

      网友评论

          本文标题:同源策略及跨域

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