为什么有些跨域 JSON 请求会失败,而另一些则不会?
我在理解 JSON 周围的安全位时遇到了一点困难,因为通常理论上不应该起作用的事情,看起来却起作用。 AFAIK,来自驻留在域 A 的页面上的脚本的调用不应该能够从域 B 接收数据。但在下面的代码中,对一个外部域的调用失败,而另一个外部域则通过。而且两者都不是打包的 JSON 调用 (jsonp)。
这是为什么呢?难道不应该禁止两者通过浏览器安全检查吗?我在 Chrome 和 Firefox 中得到相同的结果。如果我在 dropbox.com 上托管以下 html 页面,Chrome 会给出以下错误消息:
XMLHttpRequest 无法加载 http://www.odinfond.no/rest/fund/calc/fundReturn?&id=300&oneTimeInvestment=100000&oneTimeInvestmentDate=2009-11-01&endDate=2010-11 -01&货币=挪威克朗。 来源 http://dl.dropbox.com 不是 允许的 访问控制允许来源。
如果调用成功,我将得到的 JSON 响应可以通过单击 此直接链接。对其他服务的调用成功返回。我在保管箱上托管以下代码。 在这里尝试一下。
<!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">
<head>
<meta http-equiv="Content-type" content="text/html;charset=UTF-8" />
<title>JSON/JSONP test</title>
<script src="jquery.js" type="text/javascript"></script>
</head>
<body>
<script>
service = 'http://www.odinfond.no/rest/fund/calc/fundReturn?';
parameters = {
id: '300',
oneTimeInvestment:'100000',
oneTimeInvestmentDate:'2009-11-01',
endDate:'2010-11-01',
currency:'NOK'
}
$.getJSON( service, parameters, function(data) {
alert("Success");
});
service = 'http://ws.geonames.org/postalCodeLookupJSON?'
parameters = {
postalcode:1540,
country:'NO'
}
$.getJSON(service, parameters, function(data) {
alert(data.postalcodes[0].adminName2);
});
</script>
<p>Use Firebug to see JSON response</p>
</body>
</html>
I have a little trouble understanding the security bit around JSON, because often things that in theory should not work, seemingly do. AFAIK, calls from a script on a page that resides on domain A, are not supposed to be able receive data from a domain B. But in the code below the calls to one external domain fail, whereas another goes through. And neither one are packed JSON calls (jsonp).
Why is this? Should not both be disallowed from getting through the browser security checks? I get the same results in Chrome and Firefox. If I host the below html-page on dropbox.com, Chrome gives me this error message:
XMLHttpRequest cannot load
http://www.odinfond.no/rest/fund/calc/fundReturn?&id=300&oneTimeInvestment=100000&oneTimeInvestmentDate=2009-11-01&endDate=2010-11-01¤cy=NOK.
Origin http://dl.dropbox.com is not
allowed by
Access-Control-Allow-Origin.
The JSON response I would have gotten if the call went through can be seen by clicking this direct link. The call to the other service returns successfully. I host the below code on dropbox. Try it out here.
<!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">
<head>
<meta http-equiv="Content-type" content="text/html;charset=UTF-8" />
<title>JSON/JSONP test</title>
<script src="jquery.js" type="text/javascript"></script>
</head>
<body>
<script>
service = 'http://www.odinfond.no/rest/fund/calc/fundReturn?';
parameters = {
id: '300',
oneTimeInvestment:'100000',
oneTimeInvestmentDate:'2009-11-01',
endDate:'2010-11-01',
currency:'NOK'
}
$.getJSON( service, parameters, function(data) {
alert("Success");
});
service = 'http://ws.geonames.org/postalCodeLookupJSON?'
parameters = {
postalcode:1540,
country:'NO'
}
$.getJSON(service, parameters, function(data) {
alert(data.postalcodes[0].adminName2);
});
</script>
<p>Use Firebug to see JSON response</p>
</body>
</html>
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
您会注意到工作请求有一个响应标头:
这可以释放浏览器以使响应可用于脚本。 (请注意,请求始终发出,同源策略仅影响脚本是否可以访问响应)
如果“*”是主机名,则仅当当前文档的主机名与
Access-Control-Allow-Origin
标头匹配You'll notice that the working request has a response header:
This is what frees up the browser to make the response available to the script. (Note that the request is always made, the same origin policy only affects whether the response is accessible to the script or not)
If the '*' is a hostname, access is only allowed if the current document's hostname matches the
Access-Control-Allow-Origin
header浏览源代码,$.ajax() 似乎检测到远程 URL 并取代 AJAX (XMLHttpRequest
)带有良好的旧脚本标签:
[...]
Browsing the source code, it appears that $.ajax() detects remote URLs and replaces AJAX (XMLHttpRequest
) with good old script tags:
[...]