[英]Why do some cross-domain JSON-requests fail but others don't?
我在理解圍繞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¤cy=NOK 。 Access-Control-Allow-Origin不允許使用來源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>
您會注意到工作請求有一個響應頭:
Access-Control-Allow-Origin: *
這就是釋放瀏覽器以使響應可用於腳本的原因。 (請注意, 始終會發出請求,相同的原始策略只會影響腳本是否可以訪問響應)
如果“ *”是主機名,則僅當當前文檔的主機名與Access-Control-Allow-Origin
標頭匹配時才允許Access-Control-Allow-Origin
瀏覽源代碼時 ,似乎$ .ajax()檢測到遠程URL並用良好的舊腳本標記替換AJAX(XMLHttpRequest):
// Build temporary JSONP function
if ( s.dataType === "json" && (s.data && jsre.test(s.data) || jsre.test(s.url)) ) {
jsonp = s.jsonpCallback || ("jsonp" + jsc++);
// Replace the =? sequence both in the query string and the data
if ( s.data ) {
s.data = (s.data + "").replace(jsre, "=" + jsonp + "$1");
}
s.url = s.url.replace(jsre, "=" + jsonp + "$1");
// We need to make sure
// that a JSONP style response is executed properly
s.dataType = "script";
// Handle JSONP-style loading
var customJsonp = window[ jsonp ];
window[ jsonp ] = function( tmp ) {
if ( jQuery.isFunction( customJsonp ) ) {
customJsonp( tmp );
} else {
// Garbage collect
window[ jsonp ] = undefined;
try {
delete window[ jsonp ];
} catch( jsonpError ) {}
}
data = tmp;
jQuery.handleSuccess( s, xhr, status, data );
jQuery.handleComplete( s, xhr, status, data );
if ( head ) {
head.removeChild( script );
}
};
}
[...]
// Matches an absolute URL, and saves the domain
var parts = rurl.exec( s.url ),
remote = parts && (parts[1] && parts[1].toLowerCase() !== location.protocol || parts[2].toLowerCase() !== location.host);
// If we're requesting a remote document
// and trying to load JSON or Script with a GET
if ( s.dataType === "script" && type === "GET" && remote ) {
var head = document.getElementsByTagName("head")[0] || document.documentElement;
var script = document.createElement("script");
if ( s.scriptCharset ) {
script.charset = s.scriptCharset;
}
script.src = s.url;
// Handle Script loading
if ( !jsonp ) {
var done = false;
// Attach handlers for all browsers
script.onload = script.onreadystatechange = function() {
if ( !done && (!this.readyState ||
this.readyState === "loaded" || this.readyState === "complete") ) {
done = true;
jQuery.handleSuccess( s, xhr, status, data );
jQuery.handleComplete( s, xhr, status, data );
// Handle memory leak in IE
script.onload = script.onreadystatechange = null;
if ( head && script.parentNode ) {
head.removeChild( script );
}
}
};
}
// Use insertBefore instead of appendChild to circumvent an IE6 bug.
// This arises when a base node is used (#2709 and #4378).
head.insertBefore( script, head.firstChild );
// We handle everything using the script element injection
return undefined;
}
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.