深入跨域問題(1) - 初識 CORS 跨域資源共享

leiting1998發表於2018-05-16

閱讀目錄

深入跨域問題(1) - 初識 CORS 跨域資源共享(本篇)

深入跨域問題(2) - 利用 CORS 解決跨域

深入跨域問題(3) - 利用 JSONP 解決跨域

深入跨域問題(4) - 利用 代理伺服器 解決跨域

前言

跨域問題,一直困擾我們非常久,特別是在前後端分離開發條件下,幾乎一定會遇到跨域問題。

跨域也有很多解決方案:JSONP,iframe,代理,反向代理等。

如果是與後臺一起開發過的小夥伴,肯定對這一句感到熟悉:

Access-Control-Allow-Origin: *
複製程式碼

其實,這就已經屬於 CORS 跨域資源共享的內容了,但是,前端和後臺互動的時候仍然存在很多很多問題。

這些問題的主要原因:你和後臺並不熟悉 CORS ,不僅後端需要了解 CORS ,前端也要非常熟悉 !!!

在這篇文章裡面,我主要闡述 CORS 同源策略,在後續文章中,我會採用 node 模擬出跨域並解決。

深入跨域問題(1) - 初識 CORS 跨域資源共享

產生跨域的條件

瀏覽器安全的基石是 同源策略,什麼是同源策略呢?言簡意賅,就是三個相同:

  • 協議相同。
  • 域名相同。
  • 埠相同。

這三者相同的情況下,才被稱作 “同源”,同源策略,可以保證你的伺服器的介面是隱私的。

CORS 跨域資源共享就是指,在這個三者 一個或者多個不同 的情況下,允許 跨源 獲取伺服器介面的內容。

但是,既然要突破 同源策略 ,那麼 CORS 必須遵守一定 規則 來保證伺服器的資料安全。

跨域的例子:

埠不同:

假設,你的電腦現在有開啟了兩個伺服器,分別在 不同的埠

http://localhost:8080/index.html	// 傳送 ajax 請求

http://localhost:3000	// 		提供介面
複製程式碼

在這裡,這個伺服器並沒有遵守 同源策略 了,此時,就產生了跨域問題。

協議不同:

舉一個很常見的例子,雙擊開啟一個 html 檔案,你會看到瀏覽器上你會看到:

file:///Users/xxx/Documents/index.html	// 客戶端

http://localhost:3000	// 	伺服器
複製程式碼

這就是簡單的 協議不同 的跨域例子,這個例子,也是我們最好實現的例子 。。。

域名不同:

這個更明顯了:

https://www.xxx.com/index.html	// 客戶端

https://www.yyy.com		// 伺服器
複製程式碼

這個例子,我想不用過多解釋了吧。

深入跨域問題(1) - 初識 CORS 跨域資源共享

CORS 資源共享

我想,大多數人在看 MDN 文件上面的解釋時,也會一臉懵逼吧,感覺很有道理的樣子但不知道該怎麼用。

說白了,CORS 只是在 HTTP 協議內部,新增了若干個 首部欄位 ,來制定 跨域資源共享 的實現 規則

這些首部欄位,有哪些呢??? HTTP訪問控制(CORS) MDN 文件

預請求

此規則規定,處於跨域環境並在下面幾個條件下,瀏覽器會傳送兩個請求給伺服器;

舉例說明:假設客戶端需要發起 PUT 請求

  1. 首先,客戶端要傳送 OPTIONS 請求 給伺服器。
  2. 在 伺服器內部,需要對 OPTIONS 請求 ,做出一些 設定 ,告訴客戶端 是否允許訪問
  3. 客戶端確認伺服器允許該方法,最終傳送 PUT 請求;否則,丟擲錯誤,伺服器拒絕訪問此方法。

這種設定保證了伺服器的 安全性,伺服器可控制客戶端訪問的內容 !!!

觸發預請求有三種情況:

  1. 使用了某些方法,比如說 PUT, DELETE 等。
  2. Fetch 規範規定了對 CORS安全的首部欄位集合,人為設定會觸發預請求。
  3. Content-Type的值不是text/plainmultipart/form-dataapplication/x-www-form-urlencoded

由於篇幅原因,我並沒有完全列出,請查閱 HTTP訪問控制(CORS) MDN文件。

非預請求:

此規則規定,在跨域產生的條件下,某些請求和方法,不需要預請求,只傳送一個請求就行了。

簡單的請求比如說:GET, POST, HEAD 這三個方法。

思考題目:

現在,有一個場景,我們需要用 ajax 傳送一個請求,請問是否能夠觸發預請求 ?

例子1:

var data = { name: 'BruceLee', password: '123456' };

$.ajax({
    url: "http://localhost:3000",
    type: "get",
    success: function (result) {
        console.log(result);
    },
    error: function (msg) {
        console.log(msg);
    }
})
複製程式碼

例子2:

var data = { name: 'BruceLee', password: '123456' };

$.ajax({
    url: "http://localhost:3000",
    type: "post",
    success: function (result) {
        console.log(result);
    },
    error: function (msg) {
        console.log(msg);
    }
})
複製程式碼

例子3:

var data = { name: 'BruceLee', password: '123456' };

$.ajax({
    url: "http://localhost:3000",
    type: "post",
    data: JSON.stringify(data),
    contentType: 'application/json;charset=utf-8',
    success: function (result) {
        console.log(result);
    },
    error: function (msg) {
        console.log(msg);
    }
})
複製程式碼

仔細分析上述的三個例子,例子很簡單,作為前端的你,會對 CORS 擁有新的認知。

深入跨域問題(1) - 初識 CORS 跨域資源共享

參考與鳴謝:

十分感謝上述參考連結的作者,他們的文章是十分有深度和值得多多研讀的。

相關文章