CORS跨域原理

我們都知道由于同源策略的存在,導(dǎo)致我們在跨域請求數(shù)據(jù)的時候非常的麻煩

首先阻擋我們的所謂"同源"到底是什么呢?

所謂同源就是瀏覽器的一個安全機(jī)制,不同源的客戶端腳本沒有在明確授權(quán)的情況下,不能讀寫對方資源怨绣。

由于存在同源策略的限制,而又有需要跨域的業(yè)務(wù),所以就有啦CORS的出現(xiàn)

我們都知道,jsonp也可以跨域,那為什么還要使用CORS呢

  1. jsonp只可以使用 GET 方式提交
  2. 不好調(diào)試,在調(diào)用失敗的時候不會返回任何狀態(tài)碼
  3. 安全性,萬一假如提供jsonp的服務(wù)存在頁面注入漏洞凹炸,即它返回的javascript的內(nèi)容被人控制的饵溅。那么結(jié)果是什么超燃?所有調(diào)用這個 jsonp的網(wǎng)站都會存在漏洞帖汞。于是無法把危險控制在一個域名下…所以在使用jsonp的時候必須要保證使用的jsonp服務(wù)必須是安全可信的。

開始CORS

CORS 是一個W3C標(biāo)準(zhǔn),全稱是"跨域資源共享"(Cross-origin resource sharing)掀潮,他允許瀏覽器向跨源服務(wù)器發(fā)送XMLHttpRequest請求骄呼,從而克服啦 AJAX 只能同源使用的限制

CORS 需要瀏覽器和服務(wù)器同時支持共苛,整個 CORS通信過程,都是瀏覽器自動完成不需要用戶參與蜓萄,對于開發(fā)者來說隅茎,CORS的代碼和正常的 ajax 沒有什么差別,瀏覽器一旦發(fā)現(xiàn)跨域請求嫉沽,就會添加一些附加的頭信息辟犀,

CORS這么好嗎,難道就沒有缺點(diǎn)嘛绸硕?

答案肯定是NO堂竟,目前所有最新瀏覽器都支持該功能,但是萬惡的IE不能低于10

簡單請求和非簡單請求

瀏覽器將CORS請求分成兩類:簡單請求和非簡單請求

1. 請求方法是以下三種方法之一:
- HEAD
- GET
- POST
1. HTTP的頭信息不超出以下幾種字段
- Accept
- Accept-Language
- Content-Language
- Last-Event-ID
- Content-Type:只限于三個值 `application/x-www-form-urlencoded`玻佩、`multipart/form-data`出嘹、`text/plain`

凡是同時滿足上面兩種情況的就是簡單請求,反之則非簡單請求咬崔,瀏覽器對這兩種請求的處理不一樣

簡單請求

對于簡單請求來說疚漆,瀏覽器之間發(fā)送CORS請求,具體來說就是在頭信息中,增加一個origin字段

來看下例子:

GET /cors? HTTP/1.1
Host: localhost:2333
Connection: keep-alive
Origin: http://localhost:2332
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/71.0.3578.98 Safari/537.36
Accept: */*
Referer: http://localhost:2332/CORS.html
Accept-Encoding: gzip, deflate, br
Accept-Language: zh-CN,zh;q=0.9
If-None-Match: W/"1-NWoZK3kTsExUV00Ywo1G5jlUKKs"

上面的頭信息中娶聘,Origin字段用來說名本次請求來自哪個源,服務(wù)器根據(jù)這個值,決定是否同意這次請求.

如果Origin指定的源不在允許范圍之內(nèi),服務(wù)器就會返回一個正常的HTTP回應(yīng),然后瀏覽器發(fā)現(xiàn)頭信息中沒有包含Access-Control-Allow-Origin 字段,就知道出錯啦,然后拋出錯誤,反之則會出現(xiàn)這個字段(實(shí)例如下)

Access-Control-Allow-Origin: http://api.bob.com
Access-Control-Allow-Credentials: true
Access-Control-Expose-Headers: FooBar
Content-Type: text/html; charset=utf-8
  1. Access-Control-Allow-Origin 這個字段是必須的,表示接受那些域名的請求(*為所有)
  2. Access-Control-Allow-Credentials 該字段可選, 表示是否可以發(fā)送cookie
  3. Access-Control-Expose-Headers 該字段可選,XHMHttpRequest對象的方法只能夠拿到六種字段: Cache-Control闻镶、Content-Language、Content-Type丸升、Expires铆农、Last-Modified、Pragma ,如果想拿到其他的需要使用該字段指定狡耻。

如果你想要連帶Cookie一起發(fā)送,是需要服務(wù)端和客戶端配合的

// 服務(wù)端
Access-Control-Allow-Credentials: true
// 客戶端
var xhr = new XMLHttpRequest();
xhr.withCredentials = true;
// 但是如果省略withCredentials屬性的設(shè)置,有的瀏覽器還是會發(fā)送cookie的
xhr.withCredentials = false;

非簡單請求

非簡單請求則是不滿足上邊的兩種情況之一,比如請求的方式為 PUT,或者請求頭包含其他的字段

非簡單請求的CORS請求是會在正式通信之前進(jìn)行一次預(yù)檢請求

瀏覽器先詢問服務(wù)器,當(dāng)前網(wǎng)頁所在的域名是否可以請求您的服務(wù)器,以及可以使用那些HTTP動詞和頭信息,只有得到正確的答復(fù),才會進(jìn)行正式的請求

// 前端代碼
var url = 'http://localhost:2333/cors';
var xhr = new XMLHttpRequest();
xhr.open('PUT', url, true);
xhr.setRequestHeader('X-Custom-Header', 'value');
xhr.send();

由于上面的代碼使用的是 PUT 方法,并且發(fā)送啦一個自定義頭信息.所以是一個非簡單請求,當(dāng)瀏覽器發(fā)現(xiàn)這是一個非簡單請求的時候,會自動發(fā)出預(yù)檢請求,看看服務(wù)器可不可以接收這種請求,下面是"預(yù)檢"的 HTTP 頭信息

OPTIONS /cors HTTP/1.1
Origin: localhost:2333
Access-Control-Request-Method: PUT // 表示使用的什么HTTP請求方法
Access-Control-Request-Headers: X-Custom-Header // 表示瀏覽器發(fā)送的自定義字段
Host: localhost:2332
Accept-Language: zh-CN,zh;q=0.9
Connection: keep-alive
User-Agent: Mozilla/5.0...

"預(yù)檢"使用的請求方法是 OPTIONS , 表示這個請求使用來詢問的,

預(yù)檢請求后的回應(yīng)

服務(wù)器收到"預(yù)檢"請求以后墩剖,檢查了Origin、Access-Control-Request-Method和Access-Control-Request-Headers字段以后夷狰,確認(rèn)允許跨源請求岭皂,就可以做出回應(yīng)

預(yù)檢的響應(yīng)頭:

HTTP/1.1 200 OK
Date: Mon, 01 Dec 2008 01:15:39 GMT
Server: Apache/2.0.61 (Unix)
Access-Control-Allow-Origin: http://localhost:2332 // 表示http://localhost:2332可以訪問數(shù)據(jù)
Access-Control-Allow-Methods: GET, POST, PUT      
Access-Control-Allow-Headers: X-Custom-Header    
Content-Type: text/html; charset=utf-8
Content-Encoding: gzip
Content-Length: 0
Keep-Alive: timeout=2, max=100
Connection: Keep-Alive
Content-Type: text/plain

如果瀏覽器否定啦"預(yù)檢"請求,會返回一個正常的HTTP回應(yīng),但是沒有任何CORS的頭相關(guān)信息,這是瀏覽器就認(rèn)定,服務(wù)器不允許此次訪問,從而拋出錯誤

預(yù)檢之后的請求

當(dāng)預(yù)檢請求通過之后發(fā)出正經(jīng)的HTTP請求,還有一個就是一旦通過啦預(yù)檢請求就會,請求的時候就會跟簡單請求,會有一個Origin頭信息字段。

通過預(yù)檢之后的,瀏覽器發(fā)出發(fā)請求

PUT /cors HTTP/1.1
Origin: http://api.bob.com // 通過預(yù)檢之后的請求,會自動帶上Origin字段
Host: api.alice.com
X-Custom-Header: value
Accept-Language: en-US
Connection: keep-alive
User-Agent: Mozilla/5.0...
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末沼头,一起剝皮案震驚了整個濱河市爷绘,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌进倍,老刑警劉巖土至,帶你破解...
    沈念sama閱讀 217,657評論 6 505
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異猾昆,居然都是意外死亡陶因,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,889評論 3 394
  • 文/潘曉璐 我一進(jìn)店門垂蜗,熙熙樓的掌柜王于貴愁眉苦臉地迎上來楷扬,“玉大人,你說我怎么就攤上這事贴见『嫫唬” “怎么了?”我有些...
    開封第一講書人閱讀 164,057評論 0 354
  • 文/不壞的土叔 我叫張陵蝇刀,是天一觀的道長螟加。 經(jīng)常有香客問我徘溢,道長吞琐,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 58,509評論 1 293
  • 正文 為了忘掉前任然爆,我火速辦了婚禮站粟,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘曾雕。我一直安慰自己奴烙,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,562評論 6 392
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著切诀,像睡著了一般揩环。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上幅虑,一...
    開封第一講書人閱讀 51,443評論 1 302
  • 那天丰滑,我揣著相機(jī)與錄音,去河邊找鬼倒庵。 笑死褒墨,一個胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的擎宝。 我是一名探鬼主播郁妈,決...
    沈念sama閱讀 40,251評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼绍申!你這毒婦竟也來了噩咪?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 39,129評論 0 276
  • 序言:老撾萬榮一對情侶失蹤失晴,失蹤者是張志新(化名)和其女友劉穎剧腻,沒想到半個月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體涂屁,經(jīng)...
    沈念sama閱讀 45,561評論 1 314
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡书在,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,779評論 3 335
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了拆又。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片儒旬。...
    茶點(diǎn)故事閱讀 39,902評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖帖族,靈堂內(nèi)的尸體忽然破棺而出栈源,到底是詐尸還是另有隱情,我是刑警寧澤竖般,帶...
    沈念sama閱讀 35,621評論 5 345
  • 正文 年R本政府宣布甚垦,位于F島的核電站,受9級特大地震影響涣雕,放射性物質(zhì)發(fā)生泄漏艰亮。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,220評論 3 328
  • 文/蒙蒙 一挣郭、第九天 我趴在偏房一處隱蔽的房頂上張望迄埃。 院中可真熱鬧,春花似錦兑障、人聲如沸侄非。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,838評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽逞怨。三九已至者疤,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間叠赦,已是汗流浹背宛渐。 一陣腳步聲響...
    開封第一講書人閱讀 32,971評論 1 269
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留眯搭,地道東北人窥翩。 一個月前我還...
    沈念sama閱讀 48,025評論 2 370
  • 正文 我出身青樓,卻偏偏與公主長得像鳞仙,于是被迫代替她去往敵國和親寇蚊。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,843評論 2 354

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