常見的跨域解決方案

1照棋、JSONP

受瀏覽器同源策略的限制,網(wǎng)頁無法向其他域發(fā)送ajax請(qǐng)求烈炭,但在頁面中引入其他域的腳本是可以的,最常見的例子就是在頁面中引入cdn服務(wù)器上的js文件及圖片等靜態(tài)資源趴捅,JSONP正是利用這一特性實(shí)現(xiàn)了跨域。
例如拱绑,http://test.com/test.html獲取http://abc.test.com/data.php上的數(shù)據(jù),那么只需要在test.html中加入以下代碼即可:

<script>
    function handleData(data){
        // do something
    }
</script>
<script scr="http://abc.test.com/data.php?callback=handleData"></script>

其實(shí)第二個(gè)標(biāo)簽返回的是一個(gè)可執(zhí)行的js文件膀藐,data.php包含這樣一段代碼:

<?php
$callback = $_GET['callback']; 
$data = array(1,2);
echo $callback.'('.json_encode($data)')'
?>

當(dāng)?shù)诙€(gè)標(biāo)簽加載完畢后红省,就會(huì)執(zhí)行handleData([1,2])

2、document.domain

瀏覽器同源策略中第二個(gè)限制是不同域的框架之間不能進(jìn)行js交互(但可獲得彼此的window對(duì)象)
例如吧恃,在http://abc.test.com/test.html這個(gè)頁面中有一個(gè)iframe起src為http://bcd.test.com/test2.html,以下代碼會(huì)出現(xiàn)注釋中的問題

//test.html
<script>
    function ifrLoad(){
        var iframe=document.getElementById('iframe');
        var ifrWin=iframe.contentWindow; //獲得iframe的window對(duì)象(但屬性和方法幾乎不可用)
        console.log(ifrWin.document); //無法獲得document屬性
    }
</script>
<iframe src="http://bcd.test.com/test2.html" id="iframe" onload="ifrLoad()" ></iframe>

此時(shí)可通過document.domain設(shè)置當(dāng)前文檔的原始域?qū)崿F(xiàn)跨域操作,只要兩個(gè)頁面的原始域相同蚜枢,就可通過js獲得iframe中的各種屬性和方法了.

<!-- test.html   -->
<script>
   document.domain='test.com'
   function ifrLoad(){
       var iframe=document.getElementById('iframe');
       var ifrWin=iframe.contentWindow; //獲得iframe的window對(duì)象(但屬性和方法幾乎不可用)
       console.log(ifrWin.document);  //正常
   }
</script>
<iframe src="https:www.baidu.com" id="iframe" onload="ifrLoad()" ></iframe>
<!-- test2.html -->
<script>
    document.domain='test.com'
</script>

需要要注意的是针饥,d只能把document.domain設(shè)置成自身或更高一級(jí)的父域,且主域必須相同丁眼。例如:a.b.test.com 中某個(gè)文檔的document.domain 可以設(shè)成a.b.test.com、b.test.com 藐守、test.com中的任意一個(gè),但是不可以設(shè)成 c.a.b.test.com,因?yàn)檫@是當(dāng)前域的子域卢厂,也不可以設(shè)成example.com,因?yàn)橹饔蛞呀?jīng)不相同了惠啄。

3 、window.name

window.name屬性在不同的頁面(甚至不同域名)加載后依舊存在(如果沒修改則值不會(huì)變化)撵渡,并且可以支持非常長的 name 值(2MB)假設(shè)我們?cè)诎俣仁醉撛O(shè)置了window.name為'baidu',

我們?cè)谕淮翱诘刂窓谥休斎牍雀杈W(wǎng)址趋距,此時(shí)我們查看window.name會(huì)發(fā)現(xiàn)window.name依然為‘baidu’

此時(shí)我們修改window.name為'google',再次打開百度,發(fā)現(xiàn)window.name變?yōu)榱恕甮oogle’


了解了window.name屬性之后外盯,我們想要從test頁面中獲得test1中的數(shù)據(jù)就容易多了,可以首先加載test1頁面门怪,將test頁面需要的數(shù)據(jù)存在window.name中,然后加載test頁面肋殴,但貌似這種方式很蠢坦弟,解決辦法是在test頁面中設(shè)置一個(gè)隱藏的iframe標(biāo)簽用于獲取test2頁面的window.name,但需要注意的是受同源策略的限制护锤,需要在iframe中的test2加載完畢后,在iframe中加載與test同源的test3頁面烙懦。

<!-- http://abc.test.com/test.html   -->
<script>
    function loadData(){
        var iframe=document.getElementById('iframe');
        iframe.onload=fucntion(){
            var data=iframe.contentWindow.name
            console.log(data)
        }
        iframe.src='http://abc.test.com/test3.html'

    }
</script>
<iframe src="http://bcd.test.com/test2.html" id="iframe" onload="loadData()" ></iframe>

4赤炒、window.postMessage

window.postMessage是HTML5的API,允許跨域在兩個(gè)窗口/frames之間發(fā)送數(shù)據(jù)莺褒。需要注意的是調(diào)用postMessage方法的window對(duì)象是指接受消息的那個(gè)window對(duì)象。其調(diào)用方式如下:

otherWindow.postMessage(message, targetOrigin, [transfer]);

otherWindow 是其他窗口的一個(gè)引用你辣,比如iframe的contentWindow屬性尘执、執(zhí)行window.open返回的窗口對(duì)象、或者是命名過或數(shù)值索引的window.frames誊锭。
argetOrigin 是用來接收消息的那個(gè)window對(duì)象所在的域,如果不希望做限定丧靡,可以用*代替。
transfer 可選饥追,是一串和message 同時(shí)傳遞的 Transferable 對(duì)象. 這些對(duì)象的所有權(quán)將被轉(zhuǎn)移給消息的接收方罐盔,而發(fā)送一方將不再保有所有權(quán)。

<!-- http://abc.test.com/test.html   -->
<script>
    function ifrLoad(){
        var iframe=document.geElementById('iframe');
        iframe.contentWindow.postMessage('hello world!','*')
    }
</script>
<iframe src="http://bcd.test.com/test2.html" id="iframe" onload="ifrLoad()" '></iframe>
<!-- test2.html -->
<script>
    window.onmessage=function(e){
        console.log(e.data)
    }
</script>

5 、跨域資源共享(CORS)

服務(wù)器設(shè)置Access-Control-Allow-OriginHTTP響應(yīng)頭之后六孵,瀏覽器將會(huì)允許跨域請(qǐng)求幅骄,但需要瀏覽器需要支持HTML5,可以支持POST拆座,PUT等方法

HTML5標(biāo)準(zhǔn)中提出的跨域資源共享(Cross Origin Resource Share,CORS)支持其他的HTTP方法如PUT, POST等挪凑,可以從本質(zhì)上解決跨域問題。
例如搞旭,從http://a.com要訪問http://b.com的數(shù)據(jù)菇绵,通常情況下Chrome會(huì)因跨域請(qǐng)求而報(bào)錯(cuò):

XMLHttpRequest cannot load http://b.com. No 'Access-Control-Allow-Origin' header is present on the requested resource. Origin 'http://a.com' is therefore not allowed access.

錯(cuò)誤原因是被請(qǐng)求資源沒有設(shè)置Access-Control-Allow-Origin,所以我們?cè)赽.com的服務(wù)器中設(shè)置這個(gè)響應(yīng)頭字段即可:

Access-Control-Allow-Origin: * # 允許所有域名訪問咬最,或者
Access-Control-Allow-Origin: http://a.com # 只允許所有域名訪問

為 xhr設(shè)置 withCredentials后CORS方法跨域還可攜帶Cookie,但 PUT/POST 請(qǐng)求需要注意處理 preflight 請(qǐng)求

6、Proxy

可以在服務(wù)器端設(shè)置一個(gè)代理翁垂,由服務(wù)器端向跨域下的網(wǎng)站發(fā)出請(qǐng)求,再將請(qǐng)求結(jié)果返回給前端沿猜,成功避免同源策略的限制。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末橄妆,一起剝皮案震驚了整個(gè)濱河市祈坠,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌赦拘,老刑警劉巖,帶你破解...
    沈念sama閱讀 216,402評(píng)論 6 499
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件阁猜,死亡現(xiàn)場(chǎng)離奇詭異,居然都是意外死亡剃袍,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,377評(píng)論 3 392
  • 文/潘曉璐 我一進(jìn)店門憔维,熙熙樓的掌柜王于貴愁眉苦臉地迎上來研铆,“玉大人,你說我怎么就攤上這事棵红。” “怎么了逆甜?”我有些...
    開封第一講書人閱讀 162,483評(píng)論 0 353
  • 文/不壞的土叔 我叫張陵交煞,是天一觀的道長。 經(jīng)常有香客問我素征,道長,這世上最難降的妖魔是什么御毅? 我笑而不...
    開封第一講書人閱讀 58,165評(píng)論 1 292
  • 正文 為了忘掉前任端蛆,我火速辦了婚禮凤粗,結(jié)果婚禮上今豆,老公的妹妹穿的比我還像新娘。我一直安慰自己异逐,他們只是感情好插掂,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,176評(píng)論 6 388
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著,像睡著了一般院崇。 火紅的嫁衣襯著肌膚如雪袍祖。 梳的紋絲不亂的頭發(fā)上底瓣,一...
    開封第一講書人閱讀 51,146評(píng)論 1 297
  • 那天捐凭,我揣著相機(jī)與錄音凳鬓,去河邊找鬼茁肠。 笑死缩举,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的仅孩。 我是一名探鬼主播,決...
    沈念sama閱讀 40,032評(píng)論 3 417
  • 文/蒼蘭香墨 我猛地睜開眼京腥,長吁一口氣:“原來是場(chǎng)噩夢(mèng)啊……” “哼溅蛉!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起船侧,我...
    開封第一講書人閱讀 38,896評(píng)論 0 274
  • 序言:老撾萬榮一對(duì)情侶失蹤勺爱,失蹤者是張志新(化名)和其女友劉穎,沒想到半個(gè)月后琐鲁,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體人灼,經(jīng)...
    沈念sama閱讀 45,311評(píng)論 1 310
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,536評(píng)論 2 332
  • 正文 我和宋清朗相戀三年奈泪,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片涝桅。...
    茶點(diǎn)故事閱讀 39,696評(píng)論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖蕊肥,靈堂內(nèi)的尸體忽然破棺而出蛤肌,到底是詐尸還是另有隱情壁却,我是刑警寧澤裸准,帶...
    沈念sama閱讀 35,413評(píng)論 5 343
  • 正文 年R本政府宣布,位于F島的核電站盐肃,受9級(jí)特大地震影響向胡,放射性物質(zhì)發(fā)生泄漏恼蓬。R本人自食惡果不足惜僵芹,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,008評(píng)論 3 325
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望荷辕。 院中可真熱鬧件豌,春花似錦疮方、人聲如沸茧彤。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,659評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至溜歪,卻和暖如春许蓖,著一層夾襖步出監(jiān)牢的瞬間调衰,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 32,815評(píng)論 1 269
  • 我被黑心中介騙來泰國打工嚎莉, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留动壤,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 47,698評(píng)論 2 368
  • 正文 我出身青樓琼懊,卻偏偏與公主長得像,于是被迫代替她去往敵國和親启妹。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,592評(píng)論 2 353

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

  • 什么是同源策略 同源策略是指瀏覽器處于安全方面的考慮只允許本域下的接口交互。不同源的客戶端腳本在沒有明確授權(quán)的情況...
    夜流光丶閱讀 271評(píng)論 0 0
  • 什么是跨域车胡? 2.) 資源嵌入:、丧慈、、等dom標(biāo)簽逃默,還有樣式中background:url()、@font-fac...
    電影里的夢(mèng)i閱讀 2,372評(píng)論 0 5
  • 1. 什么是跨域簇搅? 跨域一詞從字面意思看,就是跨域名嘛瘩将,但實(shí)際上跨域的范圍絕對(duì)不止那么狹隘。具體概念如下:只要協(xié)議...
    w_zhuan閱讀 515評(píng)論 0 0
  • 1. 什么是跨域肠仪? 跨域一詞從字面意思看建钥,就是跨域名嘛藤韵,但實(shí)際上跨域的范圍絕對(duì)不止那么狹隘熊经。具體概念如下:只要協(xié)議...
    他在發(fā)呆閱讀 822評(píng)論 0 0
  • 打嗝其實(shí)是人類進(jìn)化的產(chǎn)物,也是身體的保護(hù)反應(yīng)然低。 在胸腔和腹腔之間,有一個(gè)肌肉膜叫膈肌雳攘,厚厚的枫笛、像帽子吨灭,把胸腔和腹腔...
    美妙的養(yǎng)生閱讀 331評(píng)論 0 0