目錄:
- 一:為什麼會存在跨域問題?
- 二:有哪些常見的跨域問題
- 三:有哪些常見的跨域解決方案?
一:為什麼會存在跨域問題?
一句話:大家都知道的 “瀏覽器同源策略” 導致的,防止跨域資源的訪問,很顯然,這樣是更安全的,要不然,大家都可以訪問淘寶的介面,支付寶的介面,那不亂套了。
二:有哪些常見的跨域問題?
- cookie,localstory,indexdb無法跨域共享
- dom無法跨域獲取和操作(iframe巢狀不同域名的頁面會常出現)
- 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請求跨域問題
- jsonp(動態生成javascript標籤,傳入callback,後端通過引數返回一段可執行的程式碼)
- webSocket(協議本身不存在跨域問題)
- cors (後端設定請求頭)
- 設定代理(常用的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: *
複製程式碼
參考文件: