這幾天的工做中,碰到了一個徹底不一樣域之間的跨域問題,發現本身居然沒法肯定能不能實現跨域,可見基礎知識徹底被拋之腦後了,趁週末整理一下。php
跨域是由於瀏覽器有同源策略,同源策略的定義是協議、域名、端口都要一致。 在跨域的狀況下,瀏覽器出於安全考慮,會限制不一樣域之間的數據或DOM交互行爲,如:html
Cookie、LocalStorage 和 IndexDB 沒法讀取。web
DOM 沒法得到。json
AJAX 請求不能發送。後端
關於同源策略的具體概念請參考MDN。跨域
爲何須要同源策略呢。那咱們試想一下若是瀏覽器沒有同源策略的狀況。瀏覽器
打個最基本的比方,如今你新建了一個站點:安全
假如沒有跨域限制,那是否是能夠隨便讀取天貓的cookie,localStorage, indexDb 等信息,若是這些信息裏有用戶名和密碼或其餘敏感信息,恰好又沒有加密的話,那豈不是都能拿到,這怎麼可能。服務器
假如沒有跨域限制,你把iframe的src指向天貓,讓用戶去登錄,而後你就能夠獲取iframe裏面的dom元素,那豈不是帳號密碼唾手可得。能夠訪問dom的話,只要iframe引入其餘公司的站點,想怎麼改就怎麼改,那好多公司都要倒閉了。cookie
假如沒有跨域限制,就能夠向天貓等站點發請求,那豈不是能夠隨便提交別人的訂單。這明顯不合理啊。世界會亂。
jsonp
原理:使用script標籤,src的值爲後端某個文件,加上callback參數。返回一段js字符串。
<!-- fn 需自定義 -->
<script src="http:xx/xx.php?callback=fn"></script>
複製代碼
缺點:只能用於 get 請求。若是須要 post,能夠試試用 form 提交來 hack。
document.domain
原理:經過設置document.domain來跨域。
缺點:只適用於主域相同,子域不一樣的業務場景。
hash
原理:利用hash改變,頁面不會刷新的特色。父窗口在iframe的src上增長hash值,並在子窗口監聽 hashChange事件。
缺點:只能經過 hash 傳遞有效信息, 只能設置字符串類型。
原理:在一個窗口(window)的生命週期內,窗口載入的全部的頁面都是共享一個 window.name。
一般作法是用一個隱藏的iframe 去加載一個同域的代理文件:proxy.html,在代理文件中設置window.name,再動態替換iframe的src爲外域的url,這樣就能夠經過window.name傳遞有效信息。
由於proxy.html 和 真實須要跳轉的外域 url 都是在同一個iframe下,window對象是同一個。
若是須要回傳數據給父窗口,就反着來。能夠先用iframe打開外域的url,在外域的文件中設置 window.name後,再跳轉到 同域的 proxy.html。父窗口這時再獲取
缺點:須要一個代理文件 proxy.html。window.name 只能設置字符串類型。
postMessage
原理:說不清, 此乃瀏覽器自帶 API。具體用法就不介紹了。
缺點:接收方須要監聽 message 事件。
webSocket
原理:webScoket採用的是 ws:// 或 wss:// 協議,非 http 協議。協議不實行同源政策,只要服務器支持,就能夠經過它進行跨源通訊,須要在服務端設置白名單。
缺點:說不清
CORS
原理:說不清
缺點:對於複雜請求,如非get,或數據格式爲json的請求, 會觸發兩次請求。一次爲 OPTIONS 預檢請求,第二次纔是正式請求。
服務器代理跨域
原理:瞭解一點 — 利用後端訪問接口不存在跨域的特色。
缺點:說不清