跨域問題

通過XHR實現(xiàn)Ajax通信的一個主要限制萎羔,來源于跨域安全策略滔吠。解決跨域總結(jié)了幾下幾種方式:
一、跨源資源共享(CORS)
在發(fā)送請求時焕议,請求頁面的源信息(協(xié)議宝磨、域名和端口)為:http://www.baidu.com
如果服務(wù)器認為這個請求可以接受,就在后臺代碼中設(shè)置Access-Control-Allow-Origin的值為 http://www.baidu.com(如果服務(wù)器認為任何請求都可以接受就設(shè)置為“*”)

二盅安、JSONP
JSONP跨域的原理:
通過動態(tài)創(chuàng)建一個script標簽唤锉,script標簽不受同源策略(CORS)限制,調(diào)用服務(wù)器端js腳本别瞭,服務(wù)器會返回一個用傳過去的回調(diào)函數(shù)名包裹著服務(wù)器返回的json數(shù)據(jù)的函數(shù)執(zhí)行窿祥,來執(zhí)行相應(yīng)的函數(shù)。

用原生js模擬jquery封裝的jsonp:
var $ = {}; $.ajax = function(param){ var url = param.url; var success = param.success; var callback = param.jsonpCallback; //callback是在全局作用域執(zhí)行的 window[callback] = function(data) { success(data); } var script = document.createElement("script"); script.src = url + "&callback=" + callback; document.getElementsByTagName("head")[0].appendChild(script); }

注: JSONP僅適用于HTTP的GET請求
JSONP有兩點不足:
1蝙寨、JSONP是從其他域中加載代碼執(zhí)行晒衩。如果其他域不安全嗤瞎,很可能會在響應(yīng)中夾帶一些惡意代碼,而此時除了完全放棄JOSNP調(diào)用之外浸遗,沒有辦法追究
2猫胁、要確定JSONP請求是否失敗應(yīng)不容易

三、圖像Ping(使用img標簽)
一個網(wǎng)頁可以從任何網(wǎng)頁中加載圖像跛锌,不用擔(dān)心跨域不跨域弃秆。
圖像Ping是與服務(wù)器進行簡單、單向的跨域通信的一種方式髓帽。請求的數(shù)據(jù)是通過查詢字符串形式發(fā)送的菠赚,而響應(yīng)可以是任意內(nèi)容,但通常是像素圖或204響應(yīng)郑藏。通過圖像Ping,瀏覽器得不到任何具體的數(shù)據(jù)衡查,但通過監(jiān)聽load和error事件,能知道響應(yīng)什么時候接收到必盖。
來看下面的例子:
var img = new Image(); img.onload = img.onerror = function() { alert("Done!"); }拌牲; img.src = "http://www.example.com/test?name=Nicholas";
這里創(chuàng)建了一個Image的實例,然后將onload和onerror事件處理程序指定為同一個函數(shù)歌粥。這樣無論是什么響應(yīng)塌忽,只要請求完成,就能得到通知失驶。

注:圖像Ping最常用于跟蹤用戶點擊頁面或動態(tài)廣告曝光次數(shù)土居。
圖像Ping有兩個主要的缺點:
1、只能發(fā)送GET請求
2嬉探、無法訪問服務(wù)器的響應(yīng)文本

四擦耀、window.postMessage和iframe
window.postMessage的功能是允許程序員跨域在兩個窗口或者frames間發(fā)送數(shù)據(jù)信息∩蹋基本上眷蜓,它就像是跨域的Ajax,但不是瀏覽器跟服務(wù)器之間交互胎围,而是在兩個客戶端之間通信账磺。除了IE6、IE7之外的所有瀏覽器都支持這個功能痊远。
比較重要的事件:
source - 消息源垮抗,消息的發(fā)送窗口或者iframe
origin - 消息源的URI(可能包含協(xié)議、域名和端口)碧聪,用來驗證數(shù)據(jù)源
data - 發(fā)送方發(fā)送給接收方的數(shù)據(jù)

注:盡管Internet Explorer8和Internet Explorer9都實現(xiàn)了postMessage API冒版,但它們也有一些局限性。最明顯的一點就是它們只允許向iframe元素發(fā)送消息逞姿。如果嘗試向特定的窗口或選項卡發(fā)送消息辞嗡,都會提示“No such interface supported”捆等。

示例:
頁面A.html在webstorm里,domain="http://localhost:9090"
頁面B.html在eclipse里续室,domain = "http://localhost:8080"

示例一:
A頁面里的iframe嵌套B頁面栋烤,A頁面給B頁面(外面給里面)發(fā)送內(nèi)容,B頁面給A頁面返回內(nèi)容挺狰,代碼如下:
A.html代碼如下:
<head lang="en">
<meta charset="UTF-8">
<title>A給B發(fā)送</title>
</head>
<body>
A-receive:<span id="receive"></span>
<button onclick="send()">點擊</button>
<iframe id="myIframe" src="http://localhost:8080/col/baidu-demo/html/receive1.html" frameborder="0"></iframe>
<script>
`
var domain = "http://localhost:8080";
var message = 'hello,B';
var iframe = document.getElementById("myIframe").contentWindow;
function send() {
iframe.postMessage(message, domain);
}

    window.addEventListener('message', function(event) {
    if(event.origin != "http://localhost:8080") return;
             console.log('received:' + event.data, event);
             document.getElementById("receive").innerHTML = event.data;
     },false);

</script> </body> B.html代碼如下: <head> <meta charset="UTF-8"> <title>A給B發(fā)送</title> </head> <body> <div>hello</div> B-receive:<span id=receive></span> <script>
var domain = "http://localhost:9090";
window.addEventListener('message', function(event) {
if(event.origin != "http://localhost:9090") return;
document.getElementById("receive").innerHTML = event.data;
event.source.postMessage("hello,A", domain);
},false);
`
</script>
</body>

示例二:
A頁面里的iframe嵌套B頁面明郭,B頁面給A頁面(里面給外面)發(fā)送內(nèi)容,代碼如下:

A.html代碼如下:
<head lang="en">
<meta charset="UTF-8">
<title>B給A發(fā)</title>
</head>
<body>
A-receive:<span id="receive"></span>
<iframe id="myIframe" src="http://localhost:8080/col/baidu-demo/html/receive.html" frameborder="0"></iframe>
<script>
window.addEventListener('message', function(event) { if(event.origin != "http://localhost:8080") return; console.log('received:' + event.data, event); document.getElementById("receive").innerHTML = event.data; },false);
</script>
</body>
B.html代碼如下:
<head>
<meta charset="UTF-8">
<title>給A發(fā)</title>
</head>
<body>
<div>hello</div>
<button onclick="send()">點擊</button>
<script>
var domain = "http://localhost:9090"; var message = 'hello,A'; console.log('blog.local:sending message:' + message); function send() { parent.postMessage(message, domain); }
</script>
</body>
示例三:
A頁面打開B頁面丰泊,A頁面給B頁面發(fā)送內(nèi)容薯定,B頁面給A頁面返回內(nèi)容

A.html代碼如下:
<head lang="en">
<meta charset="UTF-8">
<title>A給B發(fā)</title>
</head>
<body>
A-receive:<span id="receive"></span>
<button onclick="send()">點擊</button>
<script>
`
var domain = "http://localhost:8080";
var message = 'hello,B';
var openPage = window.open("http://localhost:8080/col/baidu- demo/html/receive2.html");

 function send() {
       openPage.postMessage(message, domain);
};

 window.addEventListener('message', function(event) {
       if(event.origin != "http://localhost:8080") return;
       document.getElementById("receive").innerHTML = event.data;
},false);

</script> </body> B.html代碼如下: <head> <meta charset="UTF-8"> <title>A給B發(fā)</title> </head> <body> <div>hello</div> B-receive:<span id=receive></span> <script>
var domain = "http://localhost:9090";
window.addEventListener('message', function(event) {
if(event.origin != "http://localhost:9090") return;
document.getElementById("receive").innerHTML = event.data;
window.opener.postMessage("hello,A",domain);
},false);
`
</script>
</body>

參考文獻:
http://www.webhek.com/window-postmessage-api/
《JavaScript高級程序設(shè)計》(第三版)

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市瞳购,隨后出現(xiàn)的幾起案子话侄,更是在濱河造成了極大的恐慌,老刑警劉巖学赛,帶你破解...
    沈念sama閱讀 222,000評論 6 515
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件年堆,死亡現(xiàn)場離奇詭異,居然都是意外死亡盏浇,警方通過查閱死者的電腦和手機嘀韧,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 94,745評論 3 399
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來缠捌,“玉大人,你說我怎么就攤上這事译蒂÷拢” “怎么了?”我有些...
    開封第一講書人閱讀 168,561評論 0 360
  • 文/不壞的土叔 我叫張陵柔昼,是天一觀的道長哑芹。 經(jīng)常有香客問我,道長捕透,這世上最難降的妖魔是什么聪姿? 我笑而不...
    開封第一講書人閱讀 59,782評論 1 298
  • 正文 為了忘掉前任,我火速辦了婚禮乙嘀,結(jié)果婚禮上末购,老公的妹妹穿的比我還像新娘。我一直安慰自己虎谢,他們只是感情好盟榴,可當(dāng)我...
    茶點故事閱讀 68,798評論 6 397
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著婴噩,像睡著了一般擎场。 火紅的嫁衣襯著肌膚如雪羽德。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 52,394評論 1 310
  • 那天迅办,我揣著相機與錄音宅静,去河邊找鬼。 笑死站欺,一個胖子當(dāng)著我的面吹牛姨夹,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播镊绪,決...
    沈念sama閱讀 40,952評論 3 421
  • 文/蒼蘭香墨 我猛地睜開眼匀伏,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了蝴韭?” 一聲冷哼從身側(cè)響起够颠,我...
    開封第一講書人閱讀 39,852評論 0 276
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎榄鉴,沒想到半個月后履磨,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 46,409評論 1 318
  • 正文 獨居荒郊野嶺守林人離奇死亡庆尘,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 38,483評論 3 341
  • 正文 我和宋清朗相戀三年剃诅,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片驶忌。...
    茶點故事閱讀 40,615評論 1 352
  • 序言:一個原本活蹦亂跳的男人離奇死亡矛辕,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出付魔,到底是詐尸還是另有隱情聊品,我是刑警寧澤,帶...
    沈念sama閱讀 36,303評論 5 350
  • 正文 年R本政府宣布几苍,位于F島的核電站翻屈,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏妻坝。R本人自食惡果不足惜伸眶,卻給世界環(huán)境...
    茶點故事閱讀 41,979評論 3 334
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望刽宪。 院中可真熱鬧厘贼,春花似錦、人聲如沸圣拄。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,470評論 0 24
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至赁遗,卻和暖如春署辉,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背岩四。 一陣腳步聲響...
    開封第一講書人閱讀 33,571評論 1 272
  • 我被黑心中介騙來泰國打工哭尝, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人剖煌。 一個月前我還...
    沈念sama閱讀 49,041評論 3 377
  • 正文 我出身青樓材鹦,卻偏偏與公主長得像,于是被迫代替她去往敵國和親耕姊。 傳聞我的和親對象是個殘疾皇子桶唐,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 45,630評論 2 359

推薦閱讀更多精彩內(nèi)容

  • 1. 什么是跨域? 跨域一詞從字面意思看茉兰,就是跨域名嘛尤泽,但實際上跨域的范圍絕對不止那么狹隘。具體概念如下:只要協(xié)議...
    他在發(fā)呆閱讀 824評論 0 0
  • 跨域問題的場景和解決方案多種多樣规脸,只要是做前端開發(fā)坯约,總會遇到。而且面試時也是必問的問題莫鸭。所以自己學(xué)習(xí)總結(jié)記錄一下闹丐。...
    花開_陳鳳娟閱讀 737評論 0 0
  • 一:同源策略 1.what's this 所謂同源是指,域名被因,協(xié)議卿拴,端口相同。當(dāng)瀏覽器運行一個JS腳本時會進行同源...
    吃茶葉蛋閱讀 376評論 1 0
  • 為什么會有跨越問題梨与?因為所有支持Javascript的瀏覽器都會使用同源策略這個安全策略堕花。 下面介紹5種解決跨域的...
    sdcV閱讀 2,711評論 2 3
  • 1. 什么是跨域? 跨域一詞從字面意思看,就是跨域名嘛蛋欣,但實際上跨域的范圍絕對不止那么狹隘。具體概念如下:只要協(xié)議...
    稍縱即逝_e5e9閱讀 198評論 0 0