由于CORS(跨域)本身是具有安全隱患的,因此瀏覽器默認是禁止的。但跨域卻在web開發中具有很重要的作用,也是前端dev經常為之頭痛的領域。那么,前端到底如何跨這個域呢,且往下看。
前端常見的跨域手段如下:
1.script/link/img加載外部資源
一個網站常常會加載以下外部資源:
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/js/bootstrap.min.js"></script>
<link rel="stylesheet" >
<img src=“http://www.otherdomain.com/apple.jpg” />
它們都有一個相似的特點,即js運行時一般很難去獲取其加載的資源內容。具體來說,有時候我們經常需要請求類似http://www.otherdomain.com/data.json
的文件,那我們如何能夠獲取這個文件的內容呢?
2.發送ajax
面對上面的問題,大多數人就會說“發送ajax請求啊”,具體實現如下:
$.get(‘/data.json’,function(res) {…});
可是不好意思親,你這是同源的,當然能請求到了。如果你訪問的是http://www.otherdomain.com/data.json
,那么一定會報錯,提示你不允許跨域。
其實仔細想想也不難理解,別人站點上的資源你可以通過瀏覽器打開訪問,這沒問題,因為你是處在當前的站點訪問當前的資源;但是如果你在自己的站內去請求別人的資源,還能隨隨便便請求到的話,是你你愿意不?
所以,如果你利用ajax請求到了外部資源,只有一種情況:被訪問的server端允許你跨域,即:
jsonp(返回script后調用前端方法)
后端在response header中設置了Allow-Control-Allow-Origin: matcher(例如,
*
)
3.利用iframe
其實很容易想到,iframe本身是一個html tag
,那么它和其他能夠加載資源的tag
類似,肯定也能加載外部頁面,從這一點來說它算跨域。
但有一個很重要的前提:如果加載的iframe是一個外部頁面,并且你無法修改這個頁面本身(比如某個站點的首頁),那么你只能在iframe里去操作其加載的頁面。換言之,如果你想在主頁面內訪問嵌套的iframe內容,那同樣還是有安全問題,是會被禁止的。
對于這種情況的處理,就得說說postMessage了。我們知道,頁面內嵌套頁面是會形成window鏈的,即top->parent->...,而postMessage可以實現不同window之間的消息傳遞。
假設A頁面和B頁面屬于不同的domain,A中的iframe加載了B,那么用postMessage通信的方式如下:
- 在B中添加消息監聽事件
window.addEventListener(‘message’, function(e){ … });
- 在A頁面里找到B的window后調用postMessage發送數據
window.frames[0].postMessage(’some data’, '*');
可以看到B其實已經知道自己需要跨域,所以向A暴露了事件作為間接操作dom的接口,進行了自發自收的通信方式。所以只有當我們有權限修改所加載的外部頁面時,postMessage才行得通。
到此,基本可以得出結論,如果在極端情況(只有前端,無法修改后端,無法修改外部資源,只有一個外部api或者url)下,前端是不能跨域的,這是瀏覽器的限制。
任性就是想跨域
那么也不是沒有辦法:我們可以修改瀏覽器的設置,取消瀏覽器對跨域的限制。
其實chrome extension app就允許你這么干,開發extension時,在mainfest.json
里,如下配置你的app即可讓瀏覽器對跨域沒有任何限制:
"permissions": [
"http://*/*",
"https://*/*"
]
所以許多chrome的插件也由此誕生,其中votes比較多的Allow-Control-Allow-Origin
就是一個不錯的跨域toggle工具。
可是講真的,你這么任性取消了CORS的限制,那我們還聊什么跨域呢?