1. 程式人生 > >利用Access-Control-Allow-Origin響應頭解決跨域請求原理

利用Access-Control-Allow-Origin響應頭解決跨域請求原理

 傳統的跨域請求沒有好的解決方案,無非就是jsonp和iframe,隨著跨域請求的應用越來越多,W3C提供了跨域請求的標準方案(Cross-Origin Resource Sharing)。IE8、Firefox 3.5 及其以後的版本、Chrome瀏覽器、Safari 4 等已經實現了 Cross-Origin Resource Sharing 規範,實現了跨域請求。
在伺服器響應客戶端的時候,帶上Access-Control-Allow-Origin頭資訊。

  • 如果設定 Access-Control-Allow-Origin:*,則允許所有域名的指令碼訪問該資源。
  • Access-Control-Allow-Origin:http://www.phpddt.com.com,允許特定的域名訪問。

 

 如PHP新增響應頭資訊:

 

  1. header("Access-Control-Allow-Origin: *");

 

 

 

Cross-Origin Resource Sharing協議介紹

 

傳統的Ajax請求只能獲取在同一個域名下面的資源,但是HTML5打破了這個限制,允許Ajax發起跨域的請求。瀏覽器是可以發起跨域請求的,比如你可以外鏈一個外域的圖片或者指令碼。但是Javascript指令碼是不能獲取這些資源的內容的,它只能被瀏覽器執行或渲染。

在Flash和Silverlight中,伺服器需要建立一個crossdomain.xml的檔案來允許跨域請求。如果這個檔案宣告“http://your.site”允許來自“http://my.site”的請求,則來自“http://my.site”的請求可以訪問所有“http://your.site”的檔案。這是一種整個站點層面上的控制模式,要麼你允許一個外域的站點訪問,要麼拒絕。

COR不一樣,它是頁面層次的控制模式。每一個頁面需要返回一個名為‘Access-Control-Allow-Origin’的HTTP頭來允許外域的站點訪問。你可以僅僅暴露有限的資源和有限的外域站點訪問。在COR模式中,訪問控制的職責可以放到頁面開發者的手中,而不是伺服器管理員。當然頁面開發者需要寫專門的處理程式碼來允許被外域訪問。

另外一個主要的區別是,某個站點的crossdomain.xml檔案是最早被瀏覽器獲取並分析的。如果一個外域的站點不允許被訪問,瀏覽器壓根就不會發出跨域請求。

COR則相反,Javascript先發出跨域請求,然後檢查回覆的‘Access-Control-Allow-Origin’頭。如果這個頭允許該外域訪問,則Javascript可以讀取這個回覆,否則就被禁止訪問。如果請求不是一個簡單的COR,則向外域伺服器傳送預檢驗請求,如果回覆的頭部允許訪問,則傳送跨域請求,否則禁止。

COR的實現標準就是CORS協議。

對於瀏覽器來說,COR請求都是Javascript發起的,COR請求有兩種:

1、簡單的COR請求,它可以直接向外域資源發起請求。它必須僅僅包含簡單的方法和頭,具體定義看[2] 6.1。

2、如果COR包含複雜的方法和頭,它需要發出預檢驗(Preflight)請求,它先向資源伺服器發出一個OPTIONS方法、包含“Origin”頭的請求。該回復可以控制COR請求的方法,HTTP頭以及驗證等資訊。只有該請求獲得允許以後,才會發起真實的外域請求。

下面是一個簡單的COR請求:

<script language="Javascript" type="text/javascript">

var client = new XMLHttpRequest();

client.open("GET", "http://bar.org/b")

client.onreadystatechange = function() { /* do something */ }

client.send()

</script>

假設這個請求所在頁面的域是“http://foo.org”。 如果來自“http://bar.org/b”的回覆包含這樣的頭:

Access-Control-Allow-Origin: http://foo.org

則表明,它允許來自“http://foo.org”的跨域請求。

下面的Javascript會發出預檢驗請求和真實請求:

<script language="Javascript" type="text/javascript">

var client = new XMLHttpRequest();

client.open("GET", "http://bar.org/b")

client.setRequestHeader('Content-Type','text/html')

client.onreadystatechange = function() { /* do something */ }

client.send()

</script>

由於“Content-type: text/html”不是一個簡單的頭,它會先向"http://bar.org/b"發出一個OPTIONS的HTTP請求。 回覆可能包含這樣的頭:

Access-Control-Allow-Origin: http://foo.org

Access-Control-Max-Age: 3628800

Access-Control-Allow-Methods: GET,PUT, DELETE

Access-Control-Allow-Headers: content-type

"Access-Control-Allow-Origin"表明它允許"http://foo.org"發起跨域請求

"Access-Control-Max-Age"表明在3628800秒內,不需要再發送預檢驗請求,可以快取該結果

"Access-Control-Allow-Methods"表明它允許GET、PUT、DELETE的外域請求

"Access-Control-Allow-Headers"表明它允許跨域請求包含content-type頭

如果預檢驗請求獲得通過,接下來Javascript就會發起真實的COR請求,過程跟簡單的COR請求類似。

CORS協議的實現

現在HTML5的標準如火如荼的在制定和發展中,CORS作為HTML5的一部分,在大部分現代瀏覽器中有所支援,支援(部分支援)CORS協議的瀏覽器有IE8+, Firefox5+, Chrome12+, Safari4+

服務端實現

Thinktecture.IdentityModel  這個庫已經為我們的WebAPI,MVC的專案做好了支援,具體參看[6]。

參考資料:

[1] http://code.google.com/p/html5security/wiki/CrossOriginRequestSecurity

[2] http://www.w3.org/TR/cors/

[3]Cross-origin_resource_sharing 

[4]跨域資源共享(Cross-Origin Resource Sharing)實現Ajax跨域請求

[5]http://restfulobjects.codeplex.com/wikipage?title=Cross%20Origin%20Resource%20Sharing&referringTitle=Documentation 

[6]CORS support in WebAPI, MVC and IIS with Thinktecture.IdentityModel

 

原文出處:http://blog.csdn.net/super_scan/article/details/50086159