即使正确设置了document.domain,跨子域ajax请求也被拒绝

时间:2011-10-12 06:10:37

标签: javascript jquery json cross-domain jsonp

在我的应用程序中,我在一个子域(dev.u413.com)上有一个网站,我使用jQuery向另一个子域(api.u413.com)上的JSON api发出ajax请求。当我检查Chrome开发工具和Firefox Firebug中的请求时,Access-Control-Allowed-Origin似乎阻止了我的请求。我将document.domain设置为当前域的后缀:document.domain = 'u413.com';

这是我的要求:

    $.ajax({
        dataType: 'json',
        data: { parseAsHtml: true, cli: 'help' },
        url: 'http://api.u413.com/',
        success: function (response) {
            alert(response.Command);
        }
    });

如果我将ajax请求修改为在同一个域上,则请求成功。

    $.ajax({
        dataType: 'json',
        crossDomain: false,
        data: { parseAsHtml: true, cli: 'help' },
        url: 'http://dev.u413.com/',
        success: function (response) {
            alert(response.Command);
        }
    });

为什么会这样?浏览器不应该抱怨跨域问题,因为我根据same origin policy上的指南将document.domain设置为两个子域的公共后缀。

我目前正在使用jsonp的应用程序,但我觉得正确的ajax请求应该按照我上面链接的相同原始策略工作。如果我不需要,我宁愿不使用jsonp。是否不可能跨子域定期发出ajax请求?

4 个答案:

答案 0 :(得分:20)

document.domain不适用于AJAX。它适用于跨域iframe和窗口通信。在您的情况下,您违反了相同的原始策略(表的last line),因此您需要使用JSONP或服务器端桥。

这是一个非常nice guide,它说明了实现跨域AJAX请求的不同技术。

答案 1 :(得分:5)

相同的原始政策是我必须处理的最令人沮丧的浏览器相关主题之一。傻到我,同一个域上的2台服务器无法通信。不幸的是,相同的源策略甚至考虑对同一服务器的2个请求,但在不同的端口上违反相同的源策略。我认为未来的浏览器会更好:

http://www.html5rocks.com/en/tutorials/file/xhr2/

搜索:跨源资源共享(CORS)

基本上你的服务器只需要设置一个响应标题,说“是的,允许跨域或交叉子域调用服务器xyz是可以的”。

所有浏览器都需要一段时间支持这一点我肯定(并且我必须支持ie8直到我们的大多数用户都离开它) - 但至少在隧道尽头有光。

答案 2 :(得分:1)

您还需要将document.domain = 'u413.com添加到您的其他子域。

答案 3 :(得分:0)

  

是否无法跨子域定期发出ajax请求?

这在技术上不是AJAX,但您可以通过成功跨域的表单提交来模仿AJAX请求。缺点是您无法访问响应,这将导致页面重定向到表单的ACTION URL。

而不是:

jQuery.post('https://www.com',
    'offerCode':523153,
    'accountNumber':'',
    '_item.x':'42',
    '_item.y':'21'
});

使用此:

jQuery('<form action="https://www.com" method="POST">
      <input type="text" name="offerCode" value="523153">
      <input type="text" name="accountNumber" value="">
      <input type="text" name="_item.x" value="42">
      <input type="text" name="_item.y" value="21">
    </form>').trigger('submit');