什么是同源
同源策略用于限制頁(yè)面發(fā)起不同域(源)的請(qǐng)求,用于提高請(qǐng)求的安全性。
-
如果兩個(gè)頁(yè)面的協(xié)議、端口、IP地址(域名)都相同的話,那么這兩個(gè)頁(yè)面就是同源,也就是同一個(gè)域。
舉例:以http://192.168.10.1:8080/index.html為對(duì)照源, http://192.168.10.1:8080/auth/login.html與它是同源; http://192.168.10.1:8181/index.html與它不是同源,因?yàn)槎丝诓灰粯樱?http://192.168.10.30:8080/index.html與它不是同源,因?yàn)镮P地址不一樣。
什么是跨域
- 如果你做了一些前后端分離的項(xiàng)目,由于此時(shí)前端所在的服務(wù)地址與后端所在的服務(wù)地址不一樣,你可能會(huì)遇到一個(gè)請(qǐng)求被瀏覽器攔截了的問(wèn)題,瀏覽器在檢測(cè)到當(dāng)前頁(yè)面發(fā)起的請(qǐng)求不屬于當(dāng)前域就會(huì)將其攔截,這是因?yàn)闉g覽器的“同源策略”
為什么瀏覽器會(huì)使用同源策略?它想解決什么問(wèn)題?
首先,先談一下cookie吧,cookie主要用于存儲(chǔ)一些當(dāng)前網(wǎng)站的一些數(shù)據(jù),在一些舊的web開(kāi)發(fā)中有的還會(huì)把用戶(hù)登錄信息存儲(chǔ)到cookie中。那么,從安全的角度來(lái)考慮的話,你應(yīng)該希望你的網(wǎng)站的cookie不能被另外一個(gè)網(wǎng)站使用(不然cookie中的數(shù)據(jù)就非常容易被別人竊取了),所以這就引入了域的概念,通過(guò)域來(lái)限制資源的使用,攔截跨域的資源請(qǐng)求。
- 那么我們?nèi)绾巫龅娇缬蚰? 常見(jiàn)的用于解決跨域調(diào)用接口的問(wèn)題就是CORS跨域和JSONP 跨域
CORS 跨域
如何允許跨域,一種解決方法就是目的域告訴請(qǐng)求者允許什么來(lái)源域來(lái)請(qǐng)求,那么瀏覽器就會(huì)知道B域是否允許A域發(fā)起請(qǐng)求。
-
CORS("跨域資源共享"(Cross-origin resource sharing))就是這樣一種解決手段。
CORS使得瀏覽器在向目的域發(fā)起請(qǐng)求之前先發(fā)起一個(gè)OPTIONS方式的請(qǐng)求到目的域獲取目的域的信息,比如獲取目的域允許什么域來(lái)請(qǐng)求的信息。
跨域1.png
此時(shí)目的域通常需要在響應(yīng)頭中添加以下信息:
Access-Control-Allow-Origin:用來(lái)聲明什么域可以向當(dāng)前域發(fā)起請(qǐng)求。
Access-Control-Allow-Methods:用來(lái)聲明可以向當(dāng)前域發(fā)起什么類(lèi)型的請(qǐng)求。
Access-Control-Max-Age:用來(lái)指定本次OPTIONS請(qǐng)求的有效期,單位為秒,在此期間不用發(fā)出另一條OPTIONS請(qǐng)求。
Access-Control-Allow-Headers:用來(lái)允許你附加什么特殊的請(qǐng)求頭來(lái)發(fā)起請(qǐng)求。【有些前后端分離項(xiàng)目會(huì)把token放到header中,這時(shí)候這個(gè)請(qǐng)求頭就需要Access-Control-Allow-Headers來(lái)聲明了】
【在OPTIONS請(qǐng)求成功后,瀏覽器會(huì)把這些信息記錄下來(lái),用來(lái)判斷發(fā)往目的域的請(qǐng)求是否需要攔截。如果OPTIONS請(qǐng)求失敗,那么原本要發(fā)起的請(qǐng)求就不會(huì)發(fā)送?!?/p>但有時(shí)候發(fā)請(qǐng)求是不會(huì)觸發(fā)OPTIONS請(qǐng)求的。如果這個(gè)請(qǐng)求符合以下條件的話: 1.請(qǐng)求的方式是GET、POST或HEAD。 2.請(qǐng)求頭屬于Accept,Accept-Language,Content-Language,Content-Type ,Viewport-Width。 3.請(qǐng)求頭中Content-Type屬于application/x-www-form-urlencoded、multipart/form-data、text/plain中的一個(gè)。 這種請(qǐng)求也被稱(chēng)為“簡(jiǎn)單請(qǐng)求”。
JSONP 跨域
JSONP原理:
在同源策略下,在某個(gè)服務(wù)器下的頁(yè)面是無(wú)法獲取到該服務(wù)器以外的數(shù)據(jù)的,但img、iframe、script等標(biāo)簽是個(gè)例外,這些標(biāo)簽可以通過(guò)src屬性請(qǐng)求到其他服務(wù)器上的數(shù)據(jù)。利用script標(biāo)簽的開(kāi)放策略,我們可以實(shí)現(xiàn)跨域請(qǐng)求數(shù)據(jù),當(dāng)然,也需要服務(wù)端的配合。當(dāng)我們正常地請(qǐng)求一個(gè)JSON數(shù)據(jù)的時(shí)候,服務(wù)端返回的是一串JSON類(lèi)型的數(shù)據(jù),而我們使用JSONP模式來(lái)請(qǐng)求數(shù)據(jù)的時(shí)候,服務(wù)端返回的是一段可執(zhí)行的JavaScript代碼。
-
具體思路步驟:
例: GK.com訪問(wèn)qq.com qq.com將數(shù)據(jù)寫(xiě)到 /friend.js GK.com用script標(biāo)簽引用/friend.js GK.com會(huì)事先定義好window.yy函數(shù) /friend.js執(zhí)行window.yy({friends[...]}) 然后GK.com就會(huì)通過(guò)window.yy拿到數(shù)據(jù)....
為什么我們要使用JSONP 跨域?
因?yàn)槲覀冊(cè)诳缬驎r(shí)候,由于當(dāng)前瀏覽器不支持CORS,或者因?yàn)槟承┰驐l件不支持使用CORS時(shí),我們必須使用另外一種方法來(lái)跨域。于是我們請(qǐng)求一個(gè)js文件,這個(gè)文件會(huì)執(zhí)行一個(gè)回調(diào),回調(diào)里面就有我們的思路。
- 這個(gè)回調(diào)的名字?
解:回調(diào)的名字是可以隨機(jī)生成的,我們把這個(gè)名字以CORS的參數(shù)傳遞給后臺(tái),后臺(tái)會(huì)把這個(gè)函數(shù)返回給我們并執(zhí)行。
JSONP 跨域的優(yōu)點(diǎn)缺點(diǎn)?
- 優(yōu)點(diǎn): 是可以兼容IE,可以跨域。
- 缺點(diǎn):
- 由于是script標(biāo)簽,所有它讀不到AJAX那么精確狀態(tài)并且不知道狀態(tài)碼.
- 只能發(fā)'GET'請(qǐng)求,不支持'POST'
