跨域問題

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

二、JSONP
JSONP跨域的原理:
通過動態創建一個script標簽,script標簽不受同源策略(CORS)限制,調用服務器端js腳本,服務器會返回一個用傳過去的回調函數名包裹著服務器返回的json數據的函數執行,來執行相應的函數。

用原生js模擬jquery封裝的jsonp:
var $ = {}; $.ajax = function(param){ var url = param.url; var success = param.success; var callback = param.jsonpCallback; //callback是在全局作用域執行的 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是從其他域中加載代碼執行。如果其他域不安全,很可能會在響應中夾帶一些惡意代碼,而此時除了完全放棄JOSNP調用之外,沒有辦法追究
2、要確定JSONP請求是否失敗應不容易

三、圖像Ping(使用img標簽)
一個網頁可以從任何網頁中加載圖像,不用擔心跨域不跨域。
圖像Ping是與服務器進行簡單、單向的跨域通信的一種方式。請求的數據是通過查詢字符串形式發送的,而響應可以是任意內容,但通常是像素圖或204響應。通過圖像Ping,瀏覽器得不到任何具體的數據,但通過監聽load和error事件,能知道響應什么時候接收到。
來看下面的例子:
var img = new Image(); img.onload = img.onerror = function() { alert("Done!"); }; img.src = "http://www.example.com/test?name=Nicholas";
這里創建了一個Image的實例,然后將onload和onerror事件處理程序指定為同一個函數。這樣無論是什么響應,只要請求完成,就能得到通知。

注:圖像Ping最常用于跟蹤用戶點擊頁面或動態廣告曝光次數。
圖像Ping有兩個主要的缺點:
1、只能發送GET請求
2、無法訪問服務器的響應文本

四、window.postMessage和iframe
window.postMessage的功能是允許程序員跨域在兩個窗口或者frames間發送數據信息。基本上,它就像是跨域的Ajax,但不是瀏覽器跟服務器之間交互,而是在兩個客戶端之間通信。除了IE6、IE7之外的所有瀏覽器都支持這個功能。
比較重要的事件:
source - 消息源,消息的發送窗口或者iframe
origin - 消息源的URI(可能包含協議、域名和端口),用來驗證數據源
data - 發送方發送給接收方的數據

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

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

示例一:
A頁面里的iframe嵌套B頁面,A頁面給B頁面(外面給里面)發送內容,B頁面給A頁面返回內容,代碼如下:
A.html代碼如下:
<head lang="en">
<meta charset="UTF-8">
<title>A給B發送</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發送</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頁面(里面給外面)發送內容,代碼如下:

A.html代碼如下:
<head lang="en">
<meta charset="UTF-8">
<title>B給A發</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發</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頁面發送內容,B頁面給A頁面返回內容

A.html代碼如下:
<head lang="en">
<meta charset="UTF-8">
<title>A給B發</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發</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高級程序設計》(第三版)

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市,隨后出現的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 229,763評論 6 539
  • 序言:濱河連續發生了三起死亡事件,死亡現場離奇詭異,居然都是意外死亡,警方通過查閱死者的電腦和手機,發現死者居然都...
    沈念sama閱讀 99,238評論 3 428
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人,你說我怎么就攤上這事。” “怎么了?”我有些...
    開封第一講書人閱讀 177,823評論 0 383
  • 文/不壞的土叔 我叫張陵,是天一觀的道長。 經常有香客問我,道長,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 63,604評論 1 317
  • 正文 為了忘掉前任,我火速辦了婚禮,結果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好,可當我...
    茶點故事閱讀 72,339評論 6 410
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發上,一...
    開封第一講書人閱讀 55,713評論 1 328
  • 那天,我揣著相機與錄音,去河邊找鬼。 笑死,一個胖子當著我的面吹牛,可吹牛的內容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 43,712評論 3 445
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了?” 一聲冷哼從身側響起,我...
    開封第一講書人閱讀 42,893評論 0 289
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后,有當地人在樹林里發現了一具尸體,經...
    沈念sama閱讀 49,448評論 1 335
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 41,201評論 3 357
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發現自己被綠了。 大學時的朋友給我發了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 43,397評論 1 372
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 38,944評論 5 363
  • 正文 年R本政府宣布,位于F島的核電站,受9級特大地震影響,放射性物質發生泄漏。R本人自食惡果不足惜,卻給世界環境...
    茶點故事閱讀 44,631評論 3 348
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 35,033評論 0 28
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至,卻和暖如春,著一層夾襖步出監牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 36,321評論 1 293
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個月前我還...
    沈念sama閱讀 52,128評論 3 398
  • 正文 我出身青樓,卻偏偏與公主長得像,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 48,347評論 2 377

推薦閱讀更多精彩內容

  • 1. 什么是跨域? 跨域一詞從字面意思看,就是跨域名嘛,但實際上跨域的范圍絕對不止那么狹隘。具體概念如下:只要協議...
    他在發呆閱讀 829評論 0 0
  • 跨域問題的場景和解決方案多種多樣,只要是做前端開發,總會遇到。而且面試時也是必問的問題。所以自己學習總結記錄一下。...
    花開_陳鳳娟閱讀 740評論 0 0
  • 一:同源策略 1.what's this 所謂同源是指,域名,協議,端口相同。當瀏覽器運行一個JS腳本時會進行同源...
    吃茶葉蛋閱讀 388評論 1 0
  • 為什么會有跨越問題?因為所有支持Javascript的瀏覽器都會使用同源策略這個安全策略。 下面介紹5種解決跨域的...
    sdcV閱讀 2,725評論 2 3
  • 1. 什么是跨域? 跨域一詞從字面意思看,就是跨域名嘛,但實際上跨域的范圍絕對不止那么狹隘。具體概念如下:只要協議...
    稍縱即逝_e5e9閱讀 199評論 0 0