WEB跨域資源共享:Cross-origin Resource Sharing(CORS)

  • 跨域資源共享(CORS):瀏覽器同源策略中的同源指協議+域名+端口三者完全一致,其中任何一個不同即爲跨域
    1. 瀏覽器同源策略是隔離潛在惡意文件的安全機制,限制信息傳遞和使用的邊界,不是信息的保密機制。<img><script><link>以及表單提交都可實現跨域請求,但可能會不同程度受同源策略的限制,因瀏覽器不同而異;
    2. 跨域資源共享(CORS)是一個W3C標準,是在客戶端和服務端同時遵循的情況下執行的,整個CORS通信過程,都是瀏覽器自動完成,在編碼上與同源資源共享並無不同(CORS交互中使用WithCredentials除外);
    3. 如果客戶端不支持跨域資源共享(CORS),則信息的傳遞和使用將可能受同源策略限制,但服務端返回的任然是正常的HTTP響應;
    4. IE未將端口號加入到同源策略的組成部分之中,Chrome 和 Firefox不允許從 HTTPS 的域跨域訪問 HTTP。

    下表給出了相對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 失敗 不同協議 ( https和http )
    http://store.company.com:81/dir/etc.html 失敗 不同端口 ( 81和80)
    http://news.company.com/dir/other.html 失敗 不同域名 ( news和store )
  • 規避瀏覽器同源策略:以下列舉了一些常見的可用方法
    1. document.domain:不同子域下通過設置document.domain爲相同的父級域來共享cookie 和 DOM (iframe)
       document.domain = "company.com:8080";
    
    2. 片段識別符(fragment identifier):在使用iframe場景中,父子頁通過URL #後的fragment來跨域傳遞數據
       window.onhashchange = function () {
          var message = window.location.hash;
          // ...
       }
    
    3. window.name:無論是否同源,只要在同一個窗口裏,前一個網頁設置了這個屬性,後一個網頁可以讀取它。window.name容量很大,可以放置非常長的字符串
       var data = document.getElementById('myIframe').contentWindow.name;
    
    4. window.postMessage(跨文檔通信Cross-document Messaging):這是HTML5新增的API
       var popup = window.open('http://bbb.com', 'title');
       popup.postMessage('Hello World!', 'http://bbb.com');
    
    5. jsonp:最大特點就是簡單適用,老式瀏覽器全部支持,服務器改造非常小;
    
    6. WebSocket:它使用ws://(非加密)和wss://(加密)作爲協議前綴。該協議不支持同源政策,只要服務器支持,就可以通過它進行跨源通信;
    
    7. Proxy Server:在本域之內增加Proxy Server節點負責域外數據的訪問代理
    
    8. CORS:此處不再贅述
  • 跨域資源共享(CORS)請求:通常CORS請求可分爲兩類,一類是簡單請求,另一類則是預檢請求。無論何種請求類型,只要服務端響應中未包含正確的首部如Access-Control-Allow-Origin: http://foo.example等,瀏覽器將報告錯誤。

    簡單請求簡單請求與普通請求相比,多了請求首部字段Origin,形如Origin: http://foo.example,服務端響應時則多了響應首部字段Access-Control-Allow-Origin,形如Access-Control-Allow-Origin: http://foo.example 或者 *。簡單請求須滿足所有下述條件:

    • 使用下列方法之一:
      • GET
      • HEAD
      • POST
        • Content-Type :僅POST方法的Content-Type值等於下列之一纔算作簡單請求:
          • text/plain
          • multipart/form-data
          • application/x-www-form-urlencoded
    • Fetch 規範定義了對 CORS 安全的首部字段集合,不得人爲設置該集合之外的其他首部字段。該集合爲:
      • Accept
      • Accept-Language
      • Content-Language
      • Content-Type
      • DPR
      • Downlink
      • Save-Data
      • Viewport-Width
      • Width


    預檢請求:需預檢的請求必須首先使用 OPTIONS 方法發起一個預檢請求到服務器,以獲知服務器是否允許該實際請求,如果服務端同意,再發送實際請求,這樣可以避免跨域請求對服務器的用戶數據產生未預期的影響。預檢請求須滿足所有下述條件:

    • 使用了下面任一 HTTP 方法:
      • PUT
      • DELETE
      • CONNECT
      • OPTIONS
      • TRACE
      • PATCH
    • 人爲設置了對 CORS 安全的首部字段集合之外的其他首部字段。該集合爲:
      • Accept
      • Accept-Language
      • Content-Language
      • Content-Type (but note the additional requirements below)
      • DPR
      • Downlink
      • Save-Data
      • Viewport-Width
      • Width
    •  Content-Type 的值不屬於下列之一:
      • application/x-www-form-urlencoded
      • multipart/form-data
      • text/plain

     

     

  • 跨域資源共享(CORS)附帶身份憑證:默認情況下CORS不會在請求中附帶 HTTP cookies 和 HTTP 認證信息,故需要將 withCredentials 標誌設置爲 true,如下
    var invocation = new XMLHttpRequest();
    var url = 'http://bar.other/resources/credentialed-content/';
        
    function callOtherDomain(){
      if(invocation) {
        invocation.open('GET', url, true);
        invocation.withCredentials = true;
        invocation.onreadystatechange = handler;
        invocation.send(); 
      }
    }

    但是,如果服務器端的響應中未攜帶 Access-Control-Allow-Credentials: true 或者 Access-Control-Allow-Origin: *,瀏覽器將不會把響應內容返回給請求的發送者。

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