代码改变世界

Ajax跨域问题

2013-08-29 16:52  龙恩0707  阅读(541)  评论(0编辑  收藏  举报

      JavaScript 是一种在Web开发中经常使用的前端动态脚本技术。在JavaScript中,有一个很重要的安全性限制,被称为“Same-Origin Policy”(同源策略)。这一策略对于JavaScript代码能够访问的页面内容做了很重要的限制,即JavaScript只能访问与包含它的文档 在同一域下的内容。

    JavaScript 这个安全策略在进行多iframe或多窗口编程、以及Ajax编程时显得尤为重要。根据这个策略,在hitao.com下的页面中包含的 JavaScript代码,不能访问在taobao.com域名下的页面内容;甚至不同的子域名之间的页面也不能通过JavaScript代码互相访问。 对于Ajax的影响在于,通过XMLHttpRequest实现的Ajax请求,不能向不同的域提交请求,例如,在abc.example.com下的页面,不能向def.example.com提交Ajax请求,等等。

 

下面我们分两种情况讨论跨域技术:首先讨论不同子域的跨域技术,然后讨论完全不同域的跨域技术
一: 不同的子域跨域技术。

 

   首先为了在本地电脑做demo 我们只需要在host分别绑定如下:127.0.0.1 abc.example.com 127.0.0.1 def.example.com 即可 然后假如在def.example.com域下有这么一个页面iframe1.html,JS代码为如下一个函数function test(){
            console.log(1);
        };

页面我想嵌套abc.example.com域下一个iframe  <iframe src="http://abc.example.com/iframe/iframe2.html"></iframe> 然后再iframe2.html页面通过    console.log(window.top.test());这么一句代码去调用def.example.com域下iframe1.html的test函数。

 

  好,我们注意到,这个调用是被前面讲到的“同源策略”所禁止的,JavaScript引擎会直接抛出一个异常。

 

 

  为了实现上述调用,我们可以通过修改两个页面的domain属性的方法做到。例如,我们可以将上面在abc.example.com和def.example.com下的两个页面的顶端都加上如下的JavaScript代码片段:

  document.domain = 'example.com';

 这样,两个页面就变为同域了,前面的调用也可以正常执行了。

 这 里需要注意的一点是,一个页面的document.domain属性只能设置成一个更顶级的域名(除了一级域名),但不能设置成比当前域名更深层的子域 名。例如,abc.example.com的页面只能

将它的domain设置成example.com,不能设置成 sub.abc.example.com,当然也不能设置成一级域名com。

 上面的例子讨论的是两个页面属于iframe嵌套关系的情况,当两个页面是打开与被打开的关系时,原理也完全一样。

 二:完全不同域的跨域技术:
1.通过JSONP实现跨域

 

     利用在页面中创建<script>节点的方法向不同域提交HTTP请求的方法称为JSONP,这项技术可以解决跨域提交Ajax请求的问题。JSONP的工作原理如下所述:

   假设在http://example1.com/index.php这个页面中向http://example2.com/getinfo.php提交 GET请求,我们可以将下面的JavaScript代码放在http://example1.com/index.php这个页面中来实现:

var eleScript= document.createElement("script");
    eleScript.type = "text/javascript";
    eleScript.src = "http://example2.com/getinfo.php";
    document.getElementsByTagName("HEAD")[0].appendChild(eleScript);

       当GET请求从http://example2.com/getinfo.php返回时,可以返回一段JavaScript代码,这段代码会自动执行,可以用来负责调用http://example1.com/index.php页面中的一个callback函数。

   JSONP的优点是:它不像XMLHttpRequest对象实现的Ajax请求那样受到同源策略的限制;它的兼容性更好,在更加古老的浏览器中都可以 运行,不需要XMLHttpRequest或ActiveX的支持;并且在请求完毕后可以通过调用callback的方式回传结果。

  JSONP的缺点则是:它只支持GET请求而不支持POST等其它类型的HTTP请求;它只支持跨域HTTP请求这种情况,不能解决不同域的两个页面之间如何进行JavaScript调用的问题。

 

 2. 通过iframe + form表单可以实现“post方式异步跨域”。

 

     思路: 1.通过动态创建iframe 和 动态创建 form表单 iframe的name的值与form表单target相同就可以实现异步跨域。把要传递的数据放在隐藏input里面。

     代码如下:

<div class="aa">aaaa</div>
    <script>
        $('.aa').click(function(){
            crossDomainPost();
        });
        function crossDomainPost() {
          // Add the iframe with a unique name
          var iframe = document.createElement("iframe");
          var uniqueString = "CHANGE_THIS_TO_SOME_UNIQUE_STRING";
          document.body.appendChild(iframe);
          iframe.style.display = "none";
          iframe.contentWindow.name = uniqueString;

          // construct a form with hidden inputs, targeting the iframe
          var form = document.createElement("form");
          form.target = uniqueString;
          form.action = "http://def.example.com/iframe/iframe2.html";
          form.method = "POST";

          // repeat for each parameter
          var input = document.createElement("input");
          input.type = "hidden";
          input.name = "test";
          input.value = "INSERT_YOUR_PARAMETER_VALUE_HERE";
          form.appendChild(input);

          document.body.appendChild(form);
          form.submit();
        }
        
    </script>

   思想来源  http://stackoverflow.com/questions/298745/how-do-i-send-a-cross-domain-post-request-via-javascript