Cross-Origin Resource Sharing(CORS)詳解,CORS詳解,CORS原理分析

Keywords CORS, 跨域,JS跨域調用,Ajax CORS 跨域,跨域詳解,CORS跨域原理css

Cross-Origin Resource Sharing詳解

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不一樣

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
    ......
}
相關文章
相關標籤/搜索