前端 九種跨域方式實現原理

1.jsonp

JSONP 原理
利用 script 標籤沒有跨域限制的漏洞,網頁可以得到從其他來源動態產生的 JSON 數據。JSONP 請求一定需要對方的服務器做支持纔可以。

// index.html
function jsonp({ url, params, callback }) {
  return new Promise((resolve, reject) ={
    let script = document.createElement('script')
    window[callback] = function(data) {
      resolve(data)
      document.body.removeChild(script)
    }
    params = { ...params, callback } // wd=b&callback=show
    let arrs = []
    for (let key in params) {
      arrs.push(`${key}=${params[key]}`)
    }
    script.src = `${url}?${arrs.join('&')}`
    document.body.appendChild(script)
  })
}
jsonp({
  url: 'http://localhost:3000/say',
  params: { wd: 'Iloveyou' },
  callback: 'show'
}).then(data ={
  console.log(data)
})

2.cors

CORS 需要瀏覽器和後端同時支持。IE 8 和 9 需要通過 XDomainRequest 來實現。

瀏覽器會自動進行 CORS 通信,實現 CORS 通信的關鍵是後端。只要後端實現了 CORS,就實現了跨域。

服務端設置 Access-Control-Allow-Origin 就可以開啓 CORS。 該屬性表示哪些域名可以訪問資源,如果設置通配符則表示所有網站都可以訪問資源。

雖然設置 CORS 和前端沒什麼關係,但是通過這種方式解決跨域問題的話,會在發送請求時出現兩種情況,分別爲簡單請求和複雜請求。

  1. 簡單請求

只要同時滿足以下兩大條件,就屬於簡單請求

條件 1:使用下列方法之一:

GET
HEAD
POST
條件 2:Content-Type 的值僅限於下列三者之一:

text/plain
multipart/form-data
application/x-www-form-urlencoded
請求中的任意 XMLHttpRequestUpload 對象均沒有註冊任何事件監聽器; XMLHttpRequestUpload 對象可以使用 XMLHttpRequest.upload 屬性訪問。

  1. 複雜請求

不符合以上條件的請求就肯定是複雜請求了。
複雜請求的 CORS 請求,會在正式通信之前,增加一次 HTTP 查詢請求,稱爲"預檢"請求,該請求是 option 方法的,通過該請求來知道服務端是否允許跨域請求。

3.postMessage

postMessage 是 HTML5 XMLHttpRequest Level 2 中的 API,且是爲數不多可以跨域操作的 window 屬性之一,它可用於解決以下方面的問題:

頁面和其打開的新窗口的數據傳遞
多窗口之間消息傳遞
頁面與嵌套的 iframe 消息傳遞
上面三個場景的跨域數據傳遞

4.websocket

Websocket 是 HTML5 的一個持久化的協議,它實現了瀏覽器與服務器的全雙工通信,同時也是跨域的一種解決方案。WebSocket 和 HTTP 都是應用層協議,都基於 TCP 協議。但是 WebSocket 是一種雙向通信協議,在建立連接之後,WebSocket 的 server 與 client 都能主動向對方發送或接收數據。同時,WebSocket 在建立連接時需要藉助 HTTP 協議,連接建立好了之後 client 與 server 之間的雙向通信就與 HTTP 無關了。

原生 WebSocket API 使用起來不太方便,我們使用Socket.io,它很好地封裝了 webSocket 接口,提供了更簡單、靈活的接口,也對不支持 webSocket 的瀏覽器提供了向下兼容。

5. Node 中間件代理(兩次跨域)
實現原理:同源策略是瀏覽器需要遵循的標準,而如果是服務器向服務器請求就無需遵循同源策略。
代理服務器,需要做以下幾個步驟:

接受客戶端請求 。
將請求 轉發給服務器。
拿到服務器 響應 數據。
將 響應 轉發給客戶端。

在這裏插入圖片描述
6.nginx 反向代理

實現原理類似於 Node 中間件代理,需要你搭建一箇中轉 nginx 服務器,用於轉發請求。

使用 nginx 反向代理實現跨域,是最簡單的跨域方式。只需要修改 nginx 的配置即可解決跨域問題,支持所有瀏覽器,支持 session,不需要修改任何代碼,並且不會影響服務器性能。

實現思路:通過 nginx 配置一個代理服務器(域名與 domain1 相同,端口不同)做跳板機,反向代理訪問 domain2 接口,並且可以順便修改 cookie 中 domain 信息,方便當前域 cookie 寫入,實現跨域登錄。

7.window.name + iframe

window.name 屬性的獨特之處:name 值在不同的頁面(甚至不同域名)加載後依舊存在,並且可以支持非常長的 name 值(2MB)

8.location.hash + iframe
實現原理: a.html 欲與 c.html 跨域相互通信,通過中間頁 b.html 來實現。 三個頁面,不同域之間利用 iframe 的 location.hash 傳值,相同域之間直接 js 訪問來通信。

具體實現步驟:一開始 a.html 給 c.html 傳一個 hash 值,然後 c.html 收到 hash 值後,再把 hash 值傳遞給 b.html,最後 b.html 將結果放到 a.html 的 hash 值中。

9.document.domain + iframe

該方式只能用於二級域名相同的情況下,比如 a.test.com 和 b.test.com 適用於該方式。
只需要給頁面添加 document.domain =‘test.com’ 表示二級域名都相同就可以實現跨域。

實現原理:兩個頁面都通過 js 強制設置 document.domain 爲基礎主域,就實現了同域。

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