zoukankan      html  css  js  c++  java
  • 跨域常见解决方案

      由于考虑到安全性问题,HTML的同源策略不允许JavaScript进行跨域操作,但是随着web端功能越来越多,对跨域需求逐渐增大,于是乎便催生了很多解决跨域的方法,通过网络搜索和资料查询,主要比较常见的解决方案有以下几种:

        一、设置 document.domain

    •    原理:相同主域名下不同子域页面,通过设置document.domain让他们同域;
    •    限制:此方法只适用与跨子域的,对于跨父域名,仍然不可行,且需要载入iframe页面。
     1 // url http://bentos.com/foo
     2 var ifr = document.createElement('iframe');
     3 ifr.src = 'http://b.bentos.com/foo'; 
     4 ifr.onload = function(){
     5     var ifrdoc = ifr.contentDocument || ifr.contentWindow.document;
     6     ifrdoc.getElementsById("foo").innerHTML);
     7                         };
     8 
     9 ifr.style.display = 'none';
    10 document.body.appendChild(ifr);

     上述代码所在的URL是http://bentos.com/foo,它对http://b.bentos.com/bar的DOM访问要求后者将 document.domain往上设置一级

     // URL http://b.bentos.com/bar
    1 document.domain = 'bentos.com'

    // URL: http://b.bentos.com/foo
    var data = {
        foo: 'bar',
        bar: 'foo'
    };
    callback(data);



    二、jsonp

    • 原理:<script>是可以跨域的,而且在跨域脚本中可以直接回调当前脚本的函数。
    • 限制:需要创建一个DOM对象并且添加到DOM树,只能用于GET方法
    • 1 // URL: http://b.bentos.com/foo
      2 var data = {
      3     foo: 'bar',
      4     bar: 'foo'
      5                   };
      6 callback(data);
    • 1 // URL: http://bentos.com/foo
      2 var callback = function(data){
      3     // 处理跨域请求得到的数据
      4                              };
      5 var script = $('<script>', {src: 'http://b.bentos.com/bar'});
      6 $('body').append(script);
      
      

    三、navigation 对象

    • 原理:iframe之间是共享navigator对象的,用它来传递信息
    • 要求:IE6/7

        有些人注意到了IE6/7的一个漏洞:iframe之间的window.navigator对象是共享的。 我们可以把它作为一个Messenger,通过它来传递信息。比如一个简单的委托:

    1 // bentos.com
    2 navigation.onData(){
    3     // 数据到达的处理函数
    4 }
    5 typeof navigation.getData === 'function' 
    6     || navigation.getData()
    // baidu.com
    navigation.getData = function(){
        $.get('/path/under/baidu.com')
            .success(function(data){
                typeof navigation.onData === 'function'
                    || navigation.onData(data)
            });
    }

       document.navigator类似,window.name也是当前窗口所有页面所共享的。也可以用它来传递信息。

    四、window.postMessage

    • 原理:HTML5允许窗口之间发送消息
    • 限制:浏览器需要支持HTML5,获取窗口句柄后才能相互通信

        这是一个安全的跨域通信方法,postMessage(message,targetOrigin)也是HTML5引入的特性。 可以给任何一个window发送消息,不论是否同源。第二个参数可以是*但如果你设置了一个URL但不  相符,那么该事件不会被分发。看一个普通的使用方式吧:

     1 // URL: http://bentos.com/foo
     2 var win = window.open('http://b.com/bar');
     3 win.postMessage('Hello, bar!', 'http://b.com'); 
     4 
     5 
     6 
     7 // URL: http://baidu.com/bar
     8 window.addEventListener('message',function(event) {
     9     console.log(event.data);
    10 });

     注意IE8及小于IE8的版本不支持addEventListener,需要使用attachEvent来监听事件。 参见:事件处理中的this:attachEvent, addEventListener, onclick

    五、跨域资源共享(CORS)

    • 原理:服务器设置Access-Control-Allow-OriginHTTP响应头之后,浏览器将会允许跨域请求
    • 限制:浏览器需要支持HTML5,可以支持POST,PUT等方法

       例如,从http://a.com要访问http://b.com的数据,通常情况下Chrome会因跨域请求而报错:

    1 XMLHttpRequest cannot load http://b.com. No 'Access-Control-Allow-Origin' header is present on the requested resource. Origin 'http://a.com' is therefore not allowed access.

       错误原因是被请求资源没有设置Access-Control-Allow-Origin,所以我们在b.com的服务器中设置这个响应头字段即可:

    1 Access-Control-Allow-Origin: *              # 允许所有域名访问,或者
    2 Access-Control-Allow-Origin: http://a.com   # 只允许所有域名访问

         在Html5出来之前,跨域采用常见方法为jsonp,jQuery也给出了支持。 值得注意的是它只是Hack,并没有产生额外的安全问题。 因为JSONP要成功获取数据,需要跨域资源所在服务器的配合,比如资源所在服务器需要自愿地回调一个合适的函数,所以服务器仍然有能力控制资源的跨域访问。

         跨域的正道还是要使用HTML5提供的CORS头字段以及window.postMessage, 可以支持POST, PUT等HTTP方法,从机制上解决跨域问题。 值得注意的是Access-Control-Allow-Origin头字段是资源所在服务器设置的, 访问控制的责任仍然是在提供资源的服务器一方,这和JSONP是一样的道理。

  • 相关阅读:
    请使用迭代查找一个list中最小和最大值,并返回一个tuple
    利用切片操作,实现一个trim()函数,去除字符串首尾的空格,注意不要调用str的strip()方法
    软件测试中的43个功能测试点总结
    Linux下好用的简单实用命令
    小议堆栈
    使用mac的那些稀奇古怪的事
    探索TypeScript第一步之基础类型
    Markdown的基本使用方法
    React的生命周期
    React中的通讯组件
  • 原文地址:https://www.cnblogs.com/benstos/p/5725440.html
Copyright © 2011-2022 走看看