即使正确设置了 document.domain,跨子域 ajax 请求也会被拒绝
Posted
技术标签:
【中文标题】即使正确设置了 document.domain,跨子域 ajax 请求也会被拒绝【英文标题】:Cross-subdomain ajax request denied even when document.domain is set correctly 【发布时间】:2011-12-05 20:42:58 【问题描述】:在我的应用程序中,我在一个子域 (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请求吗?
【问题讨论】:
我不想要 jsonp,这就是我的观点。我想跨子域做一个适当的 AJAX 请求,这应该是根据same origin policy 允许的。 @ALex 我已经阅读了该文件,现在我正在考虑其他方式:) @DarinDimitrov 我将如何在 api 域上设置它?它只是一个返回 JSON 数据的 api。 (例如api.u413.com/?cli=help) @AlexFord,没关系我犯了一个错误并删除了我的评论。当您执行 AJAX 时,document.domain 与您的方案无关。看我的回答。 【参考方案1】:document.domain
不适用于 AJAX。它适用于跨域 iframe 和窗口通信。在您的情况下,您违反了相同的来源策略(表的last line),因此您需要使用 JSONP 或服务器端桥接器。
这是一个非常nice guide,它说明了实现跨域 AJAX 请求的不同技术。
【讨论】:
啊,好的。谢谢您的帮助。我已经让它与 JSONP 一起工作,这很好。当我认为它应该以这种方式工作时,我无法让它工作,我只是感到沮丧。再次感谢。 “好指南”说网站被黑了:( 那么如果我使用 iframe 并使用 javascript 获取 iframe 的内容,它应该可以工作吗? 叹息...你的好指南是“被 Ben AttaCkEr 破解”。 为什么每个人都表现得像 JSONP 解决了任何事情。好的,继续,尝试使用 JSONP 进行 CORS POST,看看能走多远。【参考方案2】:同源策略是我不得不处理的与浏览器相关的最令人沮丧的话题之一。对我来说愚蠢的是,同一域上的 2 台服务器无法通信。不幸的是,同源策略甚至认为对同一服务器但在不同端口上的 2 个请求违反了同源策略。我认为未来的浏览器会变得更好:
http://www.html5rocks.com/en/tutorials/file/xhr2/
搜索:跨域资源共享 (CORS)
基本上你的服务器只需要设置一个响应头说“是的,允许跨域或跨子域调用服务器 xyz 是可以的”。
我敢肯定,所有浏览器都支持这一点还需要一段时间(而且我必须支持 ie8,直到我们的大多数用户无论如何都关闭它)——但至少隧道尽头有光明。
【讨论】:
【参考方案3】:您还需要将document.domain = 'u413.com
添加到您的其他子域。
【讨论】:
在哪里添加?它是一个只返回 JSON 的 api。 @Alex,那么 JSONP 是要走的路。document.domain
只允许两个文档协作。
也许不会,但在 CORS 之前没有太多选择。【参考方案4】:
难道不能跨子域发出常规的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');
【讨论】:
以上是关于即使正确设置了 document.domain,跨子域 ajax 请求也会被拒绝的主要内容,如果未能解决你的问题,请参考以下文章