JS跨域问题详解

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

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

  然而,当进行一些比较深入的前端编程的时候,不可避免地需要进行跨域操作,这时候“同源策略”就显得过于苛刻。本文就这个问题,概括了跨域所需要的一些技术。

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

(一)不同子域的跨域技术。
  我们分两个问题来分别讨论:第一个问题是如何跨不同子域进行JavaScript调用;第二个问题是如何向不同子域提交Ajax请求。

先来解决第一个问题,假设example.com域下有两个不同子域:abc.example.com和def.example.com。现在假设在def.example.com下面有一个页面,里面定义了一个JavaScript函数:

复制代码 代码如下:


function funcInDef() {
   .....
}

  我们想在abc.example.com下的某个页面里调用上面的函数。再假设我们要讨论的abc.example.com下面的这个页面是以iframe形式嵌入在def.example.com下面那个页面里的,这样我们可能试图在iframe里做如下调用:

复制代码 代码如下:


window.top.funcInDef();

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

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

复制代码 代码如下:


<script type="text/javascript">
    document.domain = "example.com";
</script>


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

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

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

  下面我们来解决第二个问题:如何向不同子域提交Ajax请求。

  通常情况下,我们会用与下面类似的代码来创建一个XMLHttpRequest对象:

复制代码 代码如下:


factories = [
    function() { return new XMLHttpRequest(); },
    function() { return new ActiveXObject("Msxml2.XMLHTTP"); },
    function() { return new ActiveXObject("Microsoft.XMLHTTP"); }
];
function newRequest() {
    for(var i = 0; i <</SPAN> factories.length; i++) {
        try{
            var factory = factories[i];
            return factory();
        } catch(e) {}
    }
    return null;
}


 

  上面的代码中引用ActiveXObject,是为了兼容IE6系列浏览器。每次我们调用newRequest函数,就获得了一个刚刚创建的Ajax对象,然后用这个Ajax对象来发送HTTP请求。例如,下面的代码向abc.example.com发送了一个GET请求:

复制代码 代码如下:


var request = newRequest();
request.open("GET", "" );
request.send(null);

  假设上面的代码包含在一个abc.example.com域名下的页面里,则这个GET请求可以正常发送成功,没有任何问题。然而,如果现在要向def.example.com发送请求,则出现跨域问题,JavaScript引擎抛出异常。

内容版权声明:除非注明,否则皆为本站原创文章。

转载注明出处:https://www.heiqu.com/wgswjf.html