跨域和CORS

  1. 什麼是跨域?前端

    同源:協議、域名、端口相同。不一樣源便是跨域。兩個不一樣的域名即便指向同一個IP地址,也不一樣源。nginx

  2. 同源策略限制的內容有哪些?json

    DOM 層面:限制了不一樣源 JavaScript 對當前 DOM 對象的讀寫操做;canvas

    數據層面:限制了不一樣源站點讀取當前站點的 Cookie、IndexDB、LocalStorage 等數據;segmentfault

    網絡層面:限制了經過 XMLHttpRequest 等方式將站點的數據發送給不一樣源的站點。跨域

  3. 容許跨域的三個標籤瀏覽器

    <img><link><script>服務器

  4. 跨域的解決方案有哪些?網絡

    (1) 同源策略限制下請求接口的方式:app

    1. JSONP

      • 首先是利用<script>標籤的src屬性來實現跨域。
      • 經過將前端方法做爲參數傳遞到服務器端,而後由服務器端注入參數以後返回,實現服務器端向客戶端通訊。
      • 因爲使用<script>標籤的src屬性,所以只支持 get 方法。
    2. iframeform

      • 建立一個iframe元素和form元素;
      • 若是須要在響應返回時執行一些操做,能夠在iframeload事件處理程序中添加相應代碼;
      • 指定form元素的action屬性爲請求的urlmethod屬性爲posttarget屬性爲iframename,最後調用formsubmit()方法發送請求。
    3. CORS

      分爲簡單請求和應當先發送預檢請求的請求。簡單請求設置Origin頭部,服務器返回響應數據時設置Access-Control-Allow-Origin頭部。非簡單請求先發送預檢請求,預檢請求完成後再發送實際請求。

    4. 代理

      使用nginx代理配置 server_name 爲請求發起方的域名,而後設置location攔截前端的跨域請求,再將請求代理到服務器域名便可繞過瀏覽器的同源策略。

    5. WebSocket

    (2) 同源限制下Dom查詢的方式

    1. postMessage

      使用 HTML5 提供的postMessage()方法能夠實現不一樣頁面的跨域通信。在頁面中使用postMessage()發送消息,使用addEventListener()監聽回覆的消息。

    2. document.domain

      適用於主域名相同,子域名不一樣的iframe跨域。給兩個頁面指定document.domain = 主域名便可訪問對方的window對象了。

    3. canvas操做圖片的跨域問題

      跨域的圖片只要能在網頁中正常顯示,就可使用canvasdrawImage()方法繪製出來。可是若是要對圖片進行getImageData()toDataURL()操做,則須要處理跨域問題。

      • 響應頭中設置Access-Control-Allow-Origin頭部,容許請求發送方訪問
      • 建立了Image實例後,設置實例的crossOrigin屬性值爲''crossOrigin的屬性值不爲use-credentials時,所有都會解析爲anonymous,表示不須要攜帶任何非匿名信息給服務器)
  5. 什麼是 CORS ?

    CORS 即跨域資源共享標準,它新增了一組 HTTP 首部字段,容許服務器聲明哪些源站經過瀏覽器有權限訪問哪些資源。另外,對可能對服務器數據產生反作用的 HTTP 請求方法,瀏覽器必須先使用OPTIONS方法發起一個預檢請求,從而獲知服務端是否容許該跨域請求。服務器確認容許以後,才發起實際的 HTTP 請求。在預檢請求的返回中,服務器端也能夠通知客戶端,是否須要攜帶身份憑證。

  6. CORS 的三個訪問控制場景

    (1) 簡單請求知足如下全部條件:

    1. 使用的請求方法爲GETHEADPOST中的一種;

    2. 首部字段僅限於AcceptAccept-LanguageContent-LanguageContent-TypeDPRDownlinkSave-DataViewport-WidthWidth所組成的集合中的元素;

    3. Content-Type值爲text/plainmultipart/form-dataapplication/x-www-form-urlencoded中的一個;

    4. 請求中的任意XMLHttpRequestUpload對象都沒有註冊任何事件監聽器;

    5. 請求中沒有使用ReadableStream對象。

      簡單請求中頭部字段Origin值爲本身的域名,響應頭部攜帶字段Access-Control-Allow-Origin,值爲包含請求域名的值或*,這樣便可完成跨域請求。

    (2) 應當先發送預檢請求的請求知足下述任一條件:

    1. 使用的請求方法爲PUTDELETECONNECTOPTIONSTRACEPATCH中的一種;
    2. 首部字段設置了AcceptAccept-LanguageContent-LanguageContent-TypeDPRDownlinkSave-DataViewport-WidthWidth以外的字段;
    3. Content-Type值不屬於application/x-www-form-urlencodedmultipart/form-datatext-plain之一;
    4. 請求中的XMLHttpRequestUpload對象註冊了任意多個事件監聽器;
    5. 請求中使用了ReadableStream對象。

    發送一個使用OPTIONS方法的預檢請求,用以從服務器獲取更多信息。預檢請求完成以後,發送實際請求。

    // 預檢請求頭部,這些頭部無須手動設置,使用XMLHttpRequest對象發起跨域請求時,它們已經被設置就緒
    Origin: 請求來源
    Access-Control-Request-Method: 實際請求將使用的方法
    Access-Control-Request-Headers: 實際請求將使用的自定義首部字段
    
    // 預檢請求響應頭部
    Access-Control-Allow-Origin: 容許訪問的域名
    Access-Control-Allow-Methods: 容許使用的請求方法
    Access-Control-Allow-Headers: 容許使用的自定義首部
    Access-Control-Max-Age: 響應的有效時間。在有效時間內,瀏覽器無須爲同一請求再次發起預檢請求
    複製代碼

    (3) 附帶身份憑證的請求

    • 跨域請求須要發送憑證信息時,XMLHttpRequest請求須要將withCredentials標識設置爲trueFetch請求須要將credentials: 'include'添加到fetch()方法的init對象中。響應頭部中須要攜帶Access-Control-Allow-Credentials: true頭部,不然瀏覽器不會把響應內容返回給請求發送者。
    • 附帶憑證的請求,服務器不能夠設置Access-Control-Allow-Origin的值爲*,若是設置了會致使請求失敗。

參考:

  1. 【segmentfault】不要再問我跨域的問題了:segmentfault.com/a/119000001…
  2. 解決canvas圖片getImageData, toDataURL跨域問題:www.zhangxinxu.com/wordpress/2…
  3. 【MDN】HTTP訪問控制(CORS):developer.mozilla.org/zh-CN/docs/…
相關文章
相關標籤/搜索