目錄javascript
Keywords CORS, 跨域,JS跨域調用,Ajax CORS 跨域,跨域詳解,CORS跨域原理css
Cross-Origin Resource Sharing 一般簡稱爲:CORS。它是一種機制,這個機制使用了一個額外的HTTP響應頭來賦予當前user-agent(瀏覽器)得到在當前源(origin)下使用非同源資源的權限。這句話聽起來很拗口,不易理解。可是請注意加粗字體所標記的兩個關鍵字,這裏的非同源就是Cross-Origin的概念,這裏邊的權限就是訪問非同源的資源權限。下面咱們弄清楚了這兩個關鍵字的概念就理解了什麼是Cross-Origin Resource Sharing。html
假設咱們如今在瀏覽器中輸入 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方法是否能正常執行呢?java
function getCrossRescource () { $.ajax({ url:"http://www.other.com/goods.json", success:function(){ // do something } }); }
以chrome瀏覽器爲例,假設咱們開發者工具,而後在瀏覽器中輸入上面的連接,咱們能夠看到,圖片正常顯示,樣式也正常渲染。可是getCrossRescource ()方法並未執行成功。咱們在開發者工具的制臺面板裏邊會看到錯誤信息:web
Failed to load :http://www.other.com/goods.jsonajax
No 'Access-Control-Allow-Origin' header is present on the requested resource. Origin 'http://www.myapp.com is therefore not allowed access.chrome
經過錯誤信息咱們得知:由於請求的資源不容許當前源https://www.myapp.com 訪問,由於沒有Access-Control-Allow-Origin頭信息,爲何呢?json
這是由於:出於安全的緣由,瀏覽器限制從腳本內發起跨源的HTTP請求,也就意味着限定了當前web應用程序只能請求與當前同域(同源)的HTTP資源,除非使用CORS頭信息。——原來被瀏覽器限制了。那麼那些請求會被限制呢?canvas
- 以跨站點的方式調用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
:
URL | 是否同源 | 緣由 |
---|---|---|
http://store.company.com/dir2/other.html | 是 | |
http://store.company.com/dir/inner/another.html | 是 | |
https://store.company.com/secure.html | 否 | 協議不一樣 |
http://store.company.com:81/dir/etc.html | 否 | 端口不一樣 |
http://news.company.com/dir/other.html | 否 | host不一樣 |
以上文中的例子來講明,咱們訪問的是 http://www.myapp.com/index.html 頁面,那麼當前的origin就是 http://www.myapp.com。 而這個頁面中的腳步請求的資源是 http://www.other.com/goods.json ,根據上文介紹的信息咱們能夠得知:這個是非同源的請求,且屬於瀏覽器攔截名單裏邊的請求形式。因此咱們須要經過設置CROS頭信息來完成跨域調用。
本例中,咱們須要在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
除了使用設置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 ...... }