前端跨域致命連環問

語言: CN / TW / HK

theme: fancy

本文正在參加「金石計劃」

在面試的時候,面試官問了我一個問題:“你知道如何實現跨域嗎?”

我點了點頭,心中不屑,隨後答道:

跨域是由於瀏覽器的同源策略所導致的,瀏覽器的同源策略是指只有“協議、域名、埠”相同我們才能進行通訊,當有一個不滿足的時候,我們就無法進行跨域。

現在常見的一些手段比如:“JSONP、CORS、WEBPACK配置”

JSONP

然後第二問題來了:“那你知道 JSONP 是如何實現的嗎?”

我皺眉思索了一陣:“這是一種民間的解決方案,應該是利用了 script 標籤不受瀏覽器的同源策略影響的性質來做的,當然還需要前後端的配合。”

“那你知道前後端具體是怎麼配合的嗎?”

我愣了一下,還要這麼細麼????

後來回去查了一下,我們可以這麼做

  1. 客戶端事先準備一個接收資料的全域性函式
  2. 客戶端解析道外聯的Script標籤,發出請求
  3. 服務端收到請求,返回函式的呼叫
  4. 客戶端收到資料,執行回撥。

程式碼嘛,可以看下面的: 1. 在發請求前,準備一個全域性的接收函式 ts window.myCallback = (res) => { console.log(res) } 2. 在 html 建立 script 標籤,發出請求 ts <html> .... <script> window.myCallback = (res)=>{ //這裡為上一步定義的全域性函式 console.log(res) } </script> <script url="xxx?callback=myCallback"> //script標籤的請求必須在寫在定義全域性函式之後 //這裡需將全域性函式的函式名作為引數callback的value傳遞 //這裡callback這個鍵名是前後端約定好的 </script> </body> </html> 3. 服務端接收到請求,將如下資料返回 ts myCallback({ name: 'ahreal', age: 18, }) 4. 客戶端接收到服務端的相應,相當於: ts <html> .... <script> window.myCallback = (res)=>{ //這裡為上一步定義的全域性函式 console.log(res) } </script> <script> //將接收到的資料作為script標籤裡面的內容展開執行 myCallback({ name:'ahreal', age:18 }) </script> </body> </html>

CORS

面試官看我 JSONP 矇住了,就轉頭來問我 CORS。

那你知道 CORS 一般咋使用嗎? 知道啊,我們可以配置 Access-Control-Allow-Origin 來選擇我們允許跨域的域名,如果前端請求之後返回值帶有 Access-Control-Allow-xxx 那多半是可以進行跨域請求;對於複雜請求呢,我們需要傳送一個預檢請求,需要攜帶 Access-Control-Request-Method & Access-Control-Request-Headers,如果返回值有 Access-Control-Allow-xxx 那就應該是可以。

嗯嗯,那你知道如何給 CORS 設定 Cookie 嗎?

What???

這又是個啥,之前沒見過啊。

明說不會,這一 Part 才結束。

下來查了一下是怎麼回事:

CORS 請求中,如果想要傳遞 Cookie,就要滿足以下三個條件: 1. 在請求中設定 withCredentialstrue

該屬性是一個 Boolean 型別,當非同步物件設定了 WithCredentials=true 時,瀏覽器會保留下響應的 Cookie 等資訊,並且下次傳送請求時將其攜帶。 ts var xhr = new HMLHttpRequest(); xhr.withCredentials = true; axios.default.withCredentials = true; 2. 在響應頭設定:Access-Control-Allow-Credentials 設定為 true

Access-Control-Allow-Credentials 該頭是可選的,是一個 bool 值,它若為 true 就有兩個作用:

  • 在跨域請求的響應中允許 Set-Cookie 響應頭
  • 瀏覽器收到響應後,瀏覽器根據此頭判斷是否讓自己的 withCredentials 屬性生效

  • 在響應頭中設定:Access-Control-Allow-Origin 設定為非 *

服務端的 Access-Control-Allow-Origin 設定為 非 *

服務端的 Access-Control-Allow-Origin這個響應頭的值不能說萬用字元*,而只能是具體的值,否則會出現報錯。

那麼這就是本篇文章的全部內容了

點個贊再走吧~