HTML5安全:CORS(跨域資源共享)簡介

轉載請註明:來自蔣宇捷的博客(http://blog.csdn.net/hfahe)

 前言:像CORS對於現代前端這麼重要的技術在國內基本上居然很少有人使用和提及,在百度或者Google上搜索CORS,搜到的中文文章基本都是另外一種衛星定位技術CORS的介紹,讓我等前端同學情何以堪(對比起來,用Google搜到的國外文章,基本都是跨域資源共享的介紹,說明了前端技術在國內外環境和發展的巨大差距)。

        我之前《用HTML5實現人臉識別》這篇文章中提到了“Face.com實現了CORS(跨域資源共享)。CORS系統基本上可以讓服務器暴露給其它域上文件的Ajax調用。這是一個偉大的功能,我希望更多的服務能夠使用它。”在這篇文章介紹的實現方式裏,我們可以自由的使用自己本域的JS代碼通過Ajax來調用Face.comAPI,這是一種很美妙的方式,而在以前我們很難做到這一點。

        由此我將引入和介紹CORS,希望對大家有所幫助。

定義

        CORS其實出現時間不短了,它在維基百科上的定義是:跨域資源共享(CORS )是一種網絡瀏覽器的技術規範,它爲Web服務器定義了一種方式,允許網頁從不同的域訪問其資源。而這種訪問是被同源策略所禁止的。CORS系統定義了一種瀏覽器和服務器交互的方式來確定是否允許跨域請求。 它是一個妥協,有更大的靈活性,但比起簡單地允許所有這些的要求來說更加安全。

        而W3C的官方文檔目前還是工作草案,但是正在朝着W3C推薦的方向前進。

        簡言之,CORS就是爲了讓AJAX可以實現可控的跨域訪問而生的。

以往的解決方案

        以前要實現跨域訪問,可以通過JSONP、Flash或者服務器中轉的方式來實現,但是現在我們有了CORS。

        CORS與JSONP相比,無疑更爲先進、方便和可靠。

        1、 JSONP只能實現GET請求,而CORS支持所有類型的HTTP請求。

        2、 使用CORS,開發者可以使用普通的XMLHttpRequest發起請求和獲得數據,比起JSONP有更好的錯誤處理。

        3、 JSONP主要被老的瀏覽器支持,它們往往不支持CORS,而絕大多數現代瀏覽器都已經支持了CORS(這部分會在後文瀏覽器支持部分介紹)。

詳細內容

        要使用CORS,我們需要了解前端和服務器端的使用方法。

        1、  前端

        以前我們使用Ajax,代碼類似於如下的方式:

  1. var xhr = new XMLHttpRequest();
  2. xhr.open("GET", "/hfahe", true);
  3. xhr.send();

        這裏的“/hfahe”是本域的相對路徑。

        如果我們要使用CORS,相關Ajax代碼可能如下所示:

  1. var xhr = new XMLHttpRequest();
  2. xhr.open("GET", "http://blog.csdn.net/hfahe", true);
  3. xhr.send();

        請注意,代碼與之前的區別就在於相對路徑換成了其他域的絕對路徑,也就是你要跨域訪問的接口地址。

        我們還必須提供瀏覽器回退功能檢測和支持,避免瀏覽器不支持的情況。

  1. function createCORSRequest(method, url) {
  2. var xhr = new XMLHttpRequest();
  3. if ("withCredentials" in xhr) {
  4. // 此時即支持CORS的情況
  5. // 檢查XMLHttpRequest對象是否有“withCredentials”屬性
  6. // “withCredentials”僅存在於XMLHTTPRequest2對象裏
  7. xhr.open(method, url, true);
  8. } else if (typeof!= "undefined") {
  9. // 否則檢查是否支持XDomainRequest,IE8和IE9支持
  10. // XDomainRequest僅存在於IE中,是IE用於支持CORS請求的方式
  11. xhr = new XDomainRequest();
  12. xhr.open(method, url);
  13. } else {
  14. // 否則,瀏覽器不支持CORS
  15. xhr = null;
  16. }
  17. return xhr;
  18. }
  19. var xhr = createCORSRequest('GET', url);
  20. if (!xhr) {
  21. throw new Error('CORS not supported');
  22. }

        現在如果直接使用上面的腳本進行請求,會看到瀏覽器裏控制檯的報錯如下:


        錯誤顯示的很明顯,這是因爲我們還未設置Access-Control-Allow-Origin頭。

        2、  服務器

        服務器端對於CORS的支持,主要就是通過設置Access-Control-Allow-Origin來進行的。如果瀏覽器檢測到相應的設置,就可以允許Ajax進行跨域的訪問。

        HTTP 頭的設置方法有很多,http://enable-cors.org/這篇文章裏對各種服務器和語言的設置都有詳細的介紹,下面我們主要介紹Apache和PHP裏的設置方法。

        Apache:Apache需要使用mod_headers模塊來激活HTTP頭的設置,它默認是激活的。你只需要在Apache配置文件的<Directory>, <Location>, <Files>或<VirtualHost>的配置里加入以下內容即可:

Header set Access-Control-Allow-Origin *

        PHP:只需要使用如下的代碼設置即可。

  1. <?php
  2. header("Access-Control-Allow-Origin:*");

        以上的配置的含義是允許任何域發起的請求都可以獲取當前服務器的數據。當然,這樣有很大的危險性,惡意站點可能通過XSS攻擊我們的服務器。所以我們應該儘量有針對性的對限制安全的來源,例如下面的設置使得只有http://blog.csdn.net這個域才能跨域訪問服務器的API。

Access-Control-Allow-Origin: http://blog.csdn.net

瀏覽器支持情況


        上圖爲各瀏覽器對於CORS的支持情況(綠色爲支持,數據來源:http://caniuse.com/cors),看起來相當樂觀。主流瀏覽器都已基本提供對跨域資源共享的支持,所以,CORS纔會在國外使用的如此普遍。

        上文曾經提到,IE8和IE9在某種程度上可以通過XDomainRequest來提供同樣功能的支持。

使用案例

        目前國外支持CORS的平臺有很多,例如:


        Google APIClient Library for JS

        Google CloudStorage


        Face.com API

未來

        從所有的瀏覽器都支持來看,CORS將成爲未來跨域訪問的標準解決方案。無論是自己服務器間的跨域訪問,還是開放平臺爲第三方提供API,都將採用這種統一的解決方案,因爲它簡單、高效,受到所有主流瀏覽器的支持。它非常重要,也會讓我們的網絡變得更加開放。

參考文章

        IE10中的CORS forXHR

        USING CORS

        原創文章,轉載請註明:來自蔣宇捷的博客(http://blog.csdn.net/hfahe)


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章