Keywords CORS, 跨域,JS跨域調用,Ajax CORS 跨域,跨域詳解,CORS跨域原理
Cross-Origin Resource Sharing詳解
Cross-Origin Resource Sharing 通常簡稱為:CORS。它是一種機制,這個機制使用了一個額外的HTTP響應頭來賦予當前user-agent(瀏覽器)獲得在當前源(origin)下使用非同源資源的權限。這句話聽起來很拗口,不易理解。但是請注意加粗字體所標記的兩個關鍵字,這里的非同源就是Cross-Origin的概念,這里邊的權限就是訪問非同源的資源權限。下面我們弄清楚了這兩個關鍵字的概念就理解了什么是Cross-Origin Resource Sharing。
從一個例子說起
假設我們現在在瀏覽器中輸入 http://www.myapp.com/index.html 請求index.html頁面。index.html中有一些文字信息,有一張圖片
http://www.somecloud.com/images/a.jpg ,和一個css文件 http://www.somecnd.com/a.css 。同時index.html的script節點中有如下的一個JavaScript方法。那么,圖片、樣式是否能夠正常顯示,getCrossRescource方法是否能正常執行呢?
function getCrossRescource () {
$.ajax({
url:"http://www.other.com/goods.json",
success:function(){
// do something
}
});
}
以chrome瀏覽器為例,假設我們開發者工具,然后在瀏覽器中輸入上面的鏈接,我們可以看到,圖片正常顯示,樣式也正常渲染。但是getCrossRescource ()方法並未執行成功。我們在開發者工具的制台面板里邊會看到錯誤信息:
Failed to load :http://www.other.com/goods.json
No 'Access-Control-Allow-Origin' header is present on the requested resource. Origin 'http://www.myapp.com is therefore not allowed access.
通過錯誤信息我們得知:因為請求的資源不允許當前源https://www.myapp.com 訪問,因為沒有Access-Control-Allow-Origin頭信息,為什么呢?
這是因為:出於安全的原因,瀏覽器限制從腳本內發起跨源的HTTP請求,也就意味着限定了當前web應用程序只能請求與當前同域(同源)的HTTP資源,除非使用CORS頭信息。——原來被瀏覽器限制了。那么那些請求會被限制呢?
- 以跨站點的方式調用XMLHttpRequest或者Fetch API。
- Web字體(用於CSS中@ font-face的跨域字體使用)
- WebGL textures
- 使用drawImage繪制到canvas的圖像/視頻幀。
- 樣式表(用於CSSOM訪問)
可以看到XMLHttpRequest遵循這個規則,而我們通常所使用的ajax方法就是基於XMLHttpRequest來實現的,所以在沒有使用CORS頭信息的的情況,跨源的getCrossRescource ()方法自然會無法順利執行。而上文所提到的index.html里跨源的a.jpg、a.css不屬於攔截目標,所以能夠正常顯示和渲染。
說到這里我們弄清楚了機制的問題。這個機制約定了同源的問題,並阻止了規定的這些請求形式。還剩下一個同源的概念需要解釋,那么什么叫做同源,什么叫做非同源呢?
同源的定義
給定兩個頁面,如果它們的協議、端口(如果指定了端口)、host都相同,則稱之為同源。現在給出一個源連接和一些其他連接與這個源的比較,結合下表,我們來實際的理解一下這個概念。
http://store.company.com/dir/page.html
:
CROS頭信息設置
以上文中的例子來說明,我們訪問的是 http://www.myapp.com/index.html 頁面,那么當前的origin就是 http://www.myapp.com。 而這個頁面中的腳步請求的資源是 http://www.other.com/goods.json ,根據上文介紹的信息我們可以得知:這個是非同源的請求,且屬於瀏覽器攔截名單里邊的請求形式。所以我們需要通過設置CROS頭信息來完成跨域調用。
Access-Control-Allow-Origin 頭信息設置
本例中,我們需要在http://www.other.com/goods.json所對應的服務器代碼中加入響應頭:
Access-Control-Allow-Origin: http://www.myapp.com
設置完之后,當前的源http://www.myapp.com獲得了訪問數據的權限。這個時候我們可以在請求/響應頭信息看到多了一些信息,大致如下:
GET /...
Host: ...
User-Agent: ...
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
Accept-Language: en-us,en;q=0.5
Accept-Encoding: gzip,deflate
Accept-Charset: ISO-8859-1,utf-8;q=0.7,*;q=0.7
Connection: keep-alive
Referer: http://www.myapp.com/index.html
Origin: http://www.myapp.com
--------------------------
HTTP/1.1 200 OK
Date: Mon, 01 Dec 2008 00:23:53 GMT
Server: Apache/2.0.61
Access-Control-Allow-Origin: http://www.myapp.com
Keep-Alive: timeout=2, max=100
Connection: Keep-Alive
Transfer-Encoding: chunked
Content-Type: application/xml
使用JSONP解決跨域
除了使用設置CORS頭信息,我們還可以使用JSONP來實現跨域調用。以Jquery為例,我們可以使用如下的寫法來調用跨域資源:
function corsTest(){
$.ajax({
type: "get",
url: "http://other.host/data.json",
dataType:"jsonp",
jsonp:"callback",
jsonpCallback:"callBack",
......
})
}
function callBack(data){
// do something
......
}