前端進階課程之跨域問題詳解

沉默抒懷者發表於2018-11-07

目錄:

  • 一:為什麼會存在跨域問題?
  • 二:有哪些常見的跨域問題
  • 三:有哪些常見的跨域解決方案?

一:為什麼會存在跨域問題?

一句話:大家都知道的 “瀏覽器同源策略” 導致的,防止跨域資源的訪問,很顯然,這樣是更安全的,要不然,大家都可以訪問淘寶的介面,支付寶的介面,那不亂套了。

二:有哪些常見的跨域問題?

  1. cookie,localstory,indexdb無法跨域共享
  2. dom無法跨域獲取和操作(iframe巢狀不同域名的頁面會常出現)
  3. ajax無法跨域請求

三:有哪些常見的跨域解決方案?

首先這裡明確一個概念,不同的跨域問題,需要使用不同的解決方案,而不是我們傳統印象中的,跨域問題就只有jsonp,cors等等,這些也只是針對ajax請求跨域問題的解決方案,那其他跨域問題呢?

  • 1: cookie,localstory,indexdb跨域共享問題
  • 1: cookie: 如果是一級域名相同,二級域名不同,那麼可以採用document.domain去控制。即只要兩個二級域名下的document.domain是一致的,那麼就可以cookie共享
  • iframe問題:例如在url1的頁面內要嵌入url2的頁面,這個時候,我們通常做法是採用iframe去巢狀url2的頁面,這時,如果是父子傳遞怎麼傳遞資料呢? 1: window.name. 2: url的#hash值. 3: window.postMessage(html5新增方法)三者都需要去艦艇其變化,然後獲取相應的值。 具體請看,參考文件
  • 2: ajax請求跨域問題
  1. jsonp(動態生成javascript標籤,傳入callback,後端通過引數返回一段可執行的程式碼)
  2. webSocket(協議本身不存在跨域問題)
  3. cors (後端設定請求頭)
  4. 設定代理(常用的nginx)

四:實際程式碼解決案例

1: jsonp案例

動態建立script標籤,並且執行src引入的程式碼
window.xxx = function (value) {
    console.log(value)
}
var script = document.createElement('script')
script.src = 'http://x.stuq.com:7001/json?callback=xxx'
document.body.appendChild(script)

後端此時返回的通常是如下格式:一個函式呼叫表示式
/**/ typeof xxx === 'function' && xxx({msg: "hello world"});
複製程式碼

2: window.name.window.postMessage,hash案例

以iframe為例子:
例如:當前頁面為http://localhost:8000, 然後嵌入一個src為http://localhost:9000的iframe標籤,

var iframe = document.createElement('iframe')
iframe.src = 'localhost:9000/public/hash.html'
document.body.appendChild(iframe)

//方法一:在子iframe中將要傳給父頁面的引數設定hash,在父頁面中動態監聽hash變化,從而獲取值
子iframe:
var data = '要傳的資料';
parent.location.href = `http://localhost:8000#msg=data`
父頁面:
window.onhashchange = function () {
  console.log(location.hash) //解析hash,然後獲取data
}

方法二:同理hash,在子frame中設定window.name, 然後在父元件中使用iframe.contentWindow.name獲取相應的值
子iframe:
var data = '要傳的資料';
window.name = data;
父頁面:
iframe.contentWindow.name 就可以獲取子iframe中window.name的值。


方法三:同理hash,在子iframe中觸發postMessage事件,並且傳入引數,在父頁面中監聽messasge事件,獲取相應的值
子iframe:
var data = '要傳的資料';
parent.postMessage(data, '*')
父頁面:
window.addEventListener('message', function(e) {
  console.log(JSON.parse(e.data))
}, false);

複製程式碼

3: cors案例

即在後端程式碼中設定請求頭:
Access-Control-Allow-Origin: *
複製程式碼

參考文件:

相關文章