使用Jquery和IFrame进行跨子域请求(GET,POST,...)

5
我正在尝试在我的主域名(http://foo.com)和我的API(http://api.foo.com)之间进行请求。
为了绕过跨子域限制,我在我的主页面(http.//foo.com/main.html)上使用一个iframe,指向一个名为iframe.html的页面:scripts.api.foo.com。
(scripts.api.foo.com和foo.com位于同一台服务器上,api.foo.com位于另一台服务器上) >iframe.html:
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
    <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en">
       <head>
           <title>Iframe</title>
           <meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1" />
           <script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jquery/1/jquery.min.js"></script>
       </head>
       <body>
        <script type="text/javascript">
    document.domain = 'foo.com';
    function testIframe()
    {
        $.ajax({
                    url: "http://api.foo.com/utctime",
                    timeout: 7000,
                    complete: function(jqXHR, textStatus){
                        parent.alert(jqXHR.status);}
                });
    }
        </script>
       </body>
    </html>

>main.html :

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en">
   <head>
       <title>Test</title>
       <meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1" />
       <script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jquery/1/jquery.min.js"></script>
   </head>
   <body>
    <script type="text/javascript">
document.domain = 'foo.com';
function test()
{
    pipeFrame.testIframe();
}
    </script>
    <iframe style="" src="http://scripts.api.foo.com/iframe.html" width="500" height="50" id="pipeFrame" name="pipeFrame"></iframe>
        <form>
           <p>
               <input type="button" value="Hop" onclick="test();" />
           </p>        
        </form>

   </body>
</html>

警告窗口总是包含“302”(重定向)在Firefox 3.6 / Chrome中,“0”在IE8中...虽然Firebug告诉我我的请求得到了“200 Ok”状态(没有响应)...
我已经尝试在scripts.api.foo.com/iframe.html上直接启动相同的请求,并获得了相同的状态码。
我感到非常沮丧,徒劳地在整个网络上搜索实现跨子域的清晰方式,或关于这些状态码的解释... 任何帮助都将受到欢迎。
感谢您的关注。 再见。
4个回答

5
很不幸,跨域请求的规则也会阻止子域内部的请求,即使从技术上讲它们是同一台服务器。您可以通过代理运行或使用跨域 hack 来允许 $.ajax 调用操作。这里有一篇关于使用 iFrames 和跨域内容的非常好的文章:http://softwareas.com/cross-domain-communication-with-iframes

4
我已经阅读了这篇文章,但是无法从中的理论中得出解决方案... 而代理解决方案对我来说似乎太过繁琐。跨子域是谁都想用API开发服务时经常遇到的问题... 为什么没有关于如何解决它的共识? - benjaminplanche

3

jQuery的ajax函数默认不支持IE XHR CORS所使用的XDR(即XDomainRequest)...

在你的第一个ajax调用之前添加以下代码,也许可以解决你的问题...

$(document).ready(function(e) {
    // CORS + XDR for Internet Explorer
    if ('XDomainRequest' in window&&window.XDomainRequest!==null)
    {jQuery.ajaxSettings.xhr=function(){try{return new XDomainRequest();}
    catch(e){}}; jQuery.support.cors = true;}
});

3
如果您只针对现代浏览器(例如,IE 8),则可以实现OPTIONS请求。现代浏览器在尝试执行跨站GET请求之前,会向目标(scripts.api.foo.com)发送一个OPTIONS请求,以询问在源(foo.com)上使用其脚本是否可以。然后,Web服务器可以发送一个响应,表示“当然,您可以在foo.com上使用我的脚本”。
参考:http://www.w3.org/TR/cors/

谢谢提供的信息,但我正在寻找一个更全局的解决方案...使用Iframe似乎是一个不错的主意,但尽管我可以在我的主页面(http://www.foo.com/main.html)和其Iframe(指向http://scripts.api.foo.com)之间建立通信,但从http://scripts.api.foo.com发送的请求无法到达我的api.foo.com服务器...我以为允许在(子)子域和(子)域之间发送请求,但这里不起作用。(是因为api.foo.com和scripts.api.foo.com不在同一主机上吗?)感谢您的帮助,祝您有愉快的一天。 - benjaminplanche
你无法从主框架中的 iframe 获取信息,因为这正是跨站点脚本规则旨在防止的。你可以在 iframe 中加载 URL,但如果你能够从中读取信息,那么你也可以在 iframe 中加载银行网址,并将用户的银行信息读回到你的顶级框架。 - Jack Saalwächter

0

只是随便提一下,为什么不用JSONP呢?

    $.ajax({
        url: "http://api.foo.com/utctime",
        type: "POST",
        dataType: "jsonp",
        jsonp: "callback",
        timeout: 7000,
    })
    .success(function (result) {
        //do something with the result
    })
    .error(function (err) {
        //do something if err;d
    });

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接