同源策略、跨域漱病、jsonp

1.什么是同源策略

所謂"同源"指的是"三個(gè)相同":(1)協(xié)議相同,(2)域名相同,(3)端口相同
同源策略是瀏覽器的一個(gè)功能买雾,也是瀏覽器安全的基石把曼,最初,它的含義是指漓穿,A網(wǎng)頁(yè)設(shè)置的 Cookie嗤军,B網(wǎng)頁(yè)不能打開(kāi),從而保證用戶信息的安全性晃危。隨著互聯(lián)網(wǎng)的發(fā)展叙赚,"同源政策"越來(lái)越嚴(yán)格。目前僚饭,如果非同源震叮,共有三種行為受到限制:
(1) Cookie、LocalStorage 和 IndexDB 無(wú)法讀取鳍鸵。
(2) DOM 無(wú)法獲得苇瓣。
(3) AJAX 請(qǐng)求不能發(fā)送。
換句話說(shuō):不同源的客戶端腳本在沒(méi)明確授權(quán)的情況下权纤,不能讀寫對(duì)方的資源钓简。

2.什么是跨域?跨域有幾種實(shí)現(xiàn)形式

什么是跨域:跨域即突破同源策略的限制汹想。
跨域有六種實(shí)現(xiàn)方式:

  • 1.document.domain+iframe
    應(yīng)用范圍:這種辦法只能解決主域相同而子域不同外邓,且是iframe形式的跨域;
    存在問(wèn)題:安全性古掏,當(dāng)一個(gè)站點(diǎn)(b.a.com)被攻擊后损话,另一個(gè)站點(diǎn)(c.a.com)會(huì)引起安全漏洞。
  • 2.JSONP
    應(yīng)用范圍:因?yàn)槭腔趕cript標(biāo)簽槽唾,所有只能進(jìn)行GET請(qǐng)求
    存在問(wèn)題:存在安全性問(wèn)題丧枪,可被注入可執(zhí)行的js代碼(callback=alert(1)), 對(duì)于這個(gè)問(wèn)題,只能通過(guò)外界的字符串過(guò)濾來(lái)解決庞萍,如禁止callback中傳入括號(hào)拧烦,使用正則去除左右括號(hào),callback=callback.replace(/\(/g,"")钝计,callback=callback.replace(/\)/g,"")
  • 3.CORS
    給被訪問(wèn)方設(shè)置Access-Control-Allow-Origin恋博,如在php文件頭部寫入header('Access-Control-Allow-Origin:http://a.com:8080'),表示允許來(lái)自源http://a.com:8080的請(qǐng)求。這是跨域AJAX請(qǐng)求的根本解決方法私恬。相比JSONP只能發(fā)GET請(qǐng)求债沮,CORS允許任何類型的請(qǐng)求。但是IE10及以下IE版本不支持本鸣。
  • 4.HTML5 postMessage
    這是HTML5的新功能疫衩,用postMessage支持基于web的實(shí)時(shí)消息傳遞。
  • 5.利用iframe和location.hash
    這個(gè)方法比較繞荣德,原理是利用location.hash來(lái)傳值闷煤。url中#號(hào)及其后面的內(nèi)容就是location.hash,改變hash的值頁(yè)面并不會(huì)刷新童芹,所以可以利用hash值來(lái)進(jìn)行數(shù)據(jù)傳遞。
    這種方法缺點(diǎn)也很多鲤拿,諸如數(shù)據(jù)直接暴露在了url中辐脖,數(shù)據(jù)容量和類型都有限等。
  • 6.利用window.name
    主要利用window.name值不隨url改變而改變皆愉,只要當(dāng)前頁(yè)面沒(méi)被關(guān)閉,window.name的值就不會(huì)改變艇抠。

3.jsonp 的原理是什么

JSONP是服務(wù)器與客戶端l跨域通信的常用方法幕庐。最大特點(diǎn)就是簡(jiǎn)單適用,老式瀏覽器全部支持家淤,服務(wù)器改造非常小异剥。
原理:網(wǎng)頁(yè)通過(guò)添加一個(gè)<script>元素,向服務(wù)器請(qǐng)求JSON數(shù)據(jù)絮重,這種做法不受同源政策限制冤寿;服務(wù)器收到請(qǐng)求后,將數(shù)據(jù)放在一個(gè)指定名字的回調(diào)函數(shù)里傳回來(lái)青伤。

4.CORS是什么?

CORS是跨源資源分享(Cross-Origin Resource Sharing)的縮寫督怜。它是W3C標(biāo)準(zhǔn),是跨源AJAX請(qǐng)求的根本解決方法狠角。相比JSONP只能發(fā)GET請(qǐng)求号杠,CORS允許任何類型的請(qǐng)求。
支持情況:CORS需要瀏覽器和服務(wù)器同時(shí)支持丰歌,只要服務(wù)器實(shí)現(xiàn)了CORS接口姨蟋,且瀏覽器支持該功能(目前所有瀏覽器都支持該功能,IE瀏覽器不能低于IE10)立帖,就可以跨域通信眼溶。
對(duì)于開(kāi)發(fā)者來(lái)說(shuō),CORS通信與同源的AJAX通信沒(méi)有差別晓勇,代碼完全一樣堂飞。瀏覽器一旦發(fā)現(xiàn)AJAX請(qǐng)求跨源,就會(huì)自動(dòng)添加一些附加的頭信息宵蕉,有時(shí)還會(huì)多出一次附加的請(qǐng)求酝静,但用戶不會(huì)有感覺(jué)。

實(shí)際操作

1.本地搭建服務(wù)器羡玛,演示同源策略

這里以Wampserver為例演示别智,具體步驟:
1.在Wampserver軟件的www目錄下新建兩個(gè)文件,index.html和main.js稼稿。其中薄榛,index.html的主要內(nèi)容如下:

<body>
    <h1>hello world!</h1>    
    <script src="http://apps.bdimg.com/libs/jquery/2.1.4/jquery.min.js"></script>
   
   // 分別做如下3個(gè)測(cè)試
   //測(cè)試一:a.com/index引用b.com域名下的main.js文件
     <script src="http://b.com:8080/main.js"></script>

   //測(cè)試二:a.com/index通過(guò)ajax請(qǐng)求b.com域名下的main.js文件
     <script type="text/javascript">
        $.get("http://b.com:8080/main.js",function(response){     
            console.log(response);
        }) 
    </script>

   //測(cè)試三:a.com/index 通過(guò)ajax請(qǐng)求a.com域名下的main.js文件
    <script type="text/javascript">
        $.get("http://a.com:8080/main.js",function(response){     
            console.log(response);
        })
     </script>

</body>

main.js的內(nèi)容如下:

alert (1);

2.以管理員權(quán)限運(yùn)行記事本讳窟,用記事本打開(kāi)路徑Windows/System32/drivers/etc下的hosts文件,添加如下兩條IP和域名的對(duì)應(yīng)信息敞恋。目的是讓a.com和b.com兩個(gè)域名都指向本地機(jī)丽啡。

127.0.0.1  a.com
127.0.0.1  b.com

3.啟動(dòng)Wampserver,瀏覽器地址欄輸入a.com:8080
4.測(cè)試結(jié)果:

  • 測(cè)試一結(jié)果:頁(yè)面 alert(1)硬猫,無(wú)報(bào)錯(cuò)补箍。
    說(shuō)明a.com可以引用b.com里的main.js文件(只是引用,并未讀寫)啸蜜。
  • 測(cè)試二結(jié)果:頁(yè)面無(wú)彈框坑雅,控制臺(tái)報(bào)錯(cuò)。
    受同源策略的限制衬横,a.com不能讀寫b.com域名下文件裹粤,因而控制臺(tái)會(huì)報(bào)錯(cuò),同時(shí)main.js里的腳本也不會(huì)執(zhí)行
  • 測(cè)試三結(jié)果:頁(yè)面alert(1),控制臺(tái)打印“alert(1)”
  • a.com/index通過(guò)ajax請(qǐng)求了a.com域名下的main.js文件蜂林,說(shuō)明相同域名之下遥诉,文件是可以互相讀寫的。

2.至少使用一種方式解決跨域問(wèn)題

方法一:document.domain+iframe

對(duì)于主域相同而子域不同的例子噪叙,可以通過(guò)設(shè)置document.domain的辦法來(lái)解決矮锈。如a.com和child1.a.com,可以在這兩個(gè)文件中分別加上document.domain = ‘a(chǎn).com’,然后通過(guò)a.html文件中創(chuàng)建一個(gè)iframe睁蕾,去控制iframe的contentDocument愕难。
示例:
host文件添加127.0.0.1 child1.a.com ,index文件內(nèi)容如下:

<iframe src="http://child1.a.com:8080/index2.html" frameborder="0"></iframe>
<script type="text/javascript">
        window.onload=function(){
            document.domain = "a.com";   //降域
            var iframe=window.frames[0];
            console.log(iframe.window.name);
        }
</script>

index2文件內(nèi)容如下:

<p>index2</p>
<script type="text/javascript">
        document.domain = "a.com";   //降域
        window.name="index2";
</script>

瀏覽器地址欄輸入a.com:8080惫霸,可以看到猫缭,控制臺(tái)打印出了“index2”, 即,通過(guò)document.domain方法壹店,a.com讀取到了iframe窗口的window.name屬性的值猜丹。

方法二:JSONP

雖然瀏覽器默認(rèn)禁止了跨域訪問(wèn),但并不禁止在頁(yè)面中引用其他域的JS文件硅卢,并可以自由執(zhí)行引入的JS文件中的function(包括操作cookie射窒、Dom等等)。根據(jù)這一點(diǎn)将塑,可以方便地通過(guò)創(chuàng)建script節(jié)點(diǎn)的方法來(lái)實(shí)現(xiàn)完全跨域的通信脉顿。
以下演示a.com/index引用b.com域名下的server.php文件
index文件內(nèi)容如下:

<script>
    window.foo=function(data){
        alert(data);
    }
</script>

//動(dòng)態(tài)引用
<script>
    var script=document.createElement("script");
    script.src="http://b.com:8080/server.php?callback=foo";
    document.body.appendChild(script);
</script>

// 或者靜態(tài)引用,和動(dòng)態(tài)引用沒(méi)有本質(zhì)差別
// <script src="http://b.com:8080/server.php?callback=foo"></script>

server.php文件內(nèi)容如下:

<?php
    $callback=$_GET["callback"];
    echo $callback . "('來(lái)自b.com的數(shù)據(jù)')";      //foo('來(lái)自b.com的數(shù)據(jù)')
?>

瀏覽器地址欄輸入a.com:8080,可以看到如下圖彈框点寥,說(shuō)明通過(guò)jsonp已經(jīng)成功得到了b.com下的數(shù)據(jù)艾疟。

方法三:CORS

以下演示a.com/index通過(guò)ajax請(qǐng)求b.com域名下的server.php文件
index文件內(nèi)容如下:

<script>
      $.get("http://b.com:8080/server.php?callback=小明",function(response){     
           console.log(response);    //小明:18
       })
    </script>

server.php文件內(nèi)容如下:

<?php
    header('Access-Control-Allow-Origin:http://a.com:8080');  //設(shè)置php頭部信息,表示允許a.com訪問(wèn)
    $arr = array('小明' => "18", "花花"=>"16","天天"=>"15");
    $callback=$_GET["callback"];
    echo $callback .":".$arr[$callback];
?>

瀏覽器地址欄輸入a.com:8080,可以看到控制臺(tái)打印出“小明:18”,說(shuō)明通過(guò)給php設(shè)置Access-Control-Allow-Origin頭部信息可以實(shí)現(xiàn)跨域蔽莱。


最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末弟疆,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子盗冷,更是在濱河造成了極大的恐慌怠苔,老刑警劉巖,帶你破解...
    沈念sama閱讀 212,816評(píng)論 6 492
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件仪糖,死亡現(xiàn)場(chǎng)離奇詭異柑司,居然都是意外死亡,警方通過(guò)查閱死者的電腦和手機(jī)锅劝,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,729評(píng)論 3 385
  • 文/潘曉璐 我一進(jìn)店門帜羊,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái),“玉大人鸠天,你說(shuō)我怎么就攤上這事≌室觯” “怎么了稠集?”我有些...
    開(kāi)封第一講書人閱讀 158,300評(píng)論 0 348
  • 文/不壞的土叔 我叫張陵,是天一觀的道長(zhǎng)饥瓷。 經(jīng)常有香客問(wèn)我剥纷,道長(zhǎng),這世上最難降的妖魔是什么呢铆? 我笑而不...
    開(kāi)封第一講書人閱讀 56,780評(píng)論 1 285
  • 正文 為了忘掉前任晦鞋,我火速辦了婚禮,結(jié)果婚禮上棺克,老公的妹妹穿的比我還像新娘悠垛。我一直安慰自己,他們只是感情好娜谊,可當(dāng)我...
    茶點(diǎn)故事閱讀 65,890評(píng)論 6 385
  • 文/花漫 我一把揭開(kāi)白布确买。 她就那樣靜靜地躺著,像睡著了一般纱皆。 火紅的嫁衣襯著肌膚如雪湾趾。 梳的紋絲不亂的頭發(fā)上,一...
    開(kāi)封第一講書人閱讀 50,084評(píng)論 1 291
  • 那天派草,我揣著相機(jī)與錄音搀缠,去河邊找鬼。 笑死近迁,一個(gè)胖子當(dāng)著我的面吹牛艺普,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 39,151評(píng)論 3 410
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼衷敌,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼勿侯!你這毒婦竟也來(lái)了?” 一聲冷哼從身側(cè)響起缴罗,我...
    開(kāi)封第一講書人閱讀 37,912評(píng)論 0 268
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤助琐,失蹤者是張志新(化名)和其女友劉穎,沒(méi)想到半個(gè)月后面氓,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體兵钮,經(jīng)...
    沈念sama閱讀 44,355評(píng)論 1 303
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,666評(píng)論 2 327
  • 正文 我和宋清朗相戀三年舌界,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了掘譬。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 38,809評(píng)論 1 341
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡呻拌,死狀恐怖葱轩,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情藐握,我是刑警寧澤靴拱,帶...
    沈念sama閱讀 34,504評(píng)論 4 334
  • 正文 年R本政府宣布,位于F島的核電站猾普,受9級(jí)特大地震影響袜炕,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜初家,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 40,150評(píng)論 3 317
  • 文/蒙蒙 一偎窘、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧溜在,春花似錦陌知、人聲如沸。這莊子的主人今日做“春日...
    開(kāi)封第一講書人閱讀 30,882評(píng)論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)。三九已至培遵,卻和暖如春浙芙,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背籽腕。 一陣腳步聲響...
    開(kāi)封第一講書人閱讀 32,121評(píng)論 1 267
  • 我被黑心中介騙來(lái)泰國(guó)打工嗡呼, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人皇耗。 一個(gè)月前我還...
    沈念sama閱讀 46,628評(píng)論 2 362
  • 正文 我出身青樓南窗,卻偏偏與公主長(zhǎng)得像,于是被迫代替她去往敵國(guó)和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子万伤,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 43,724評(píng)論 2 351

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