什麼是跨域以及幾種簡單解決方案

什麼是跨域?

要明白什麼是跨域以前,首先要明白什麼是同源策略php

同源策略就是用來限制從一個源加載的文檔或腳本與來自另外一個源的資源進行交互。那怎樣判斷是不是同源呢?html

若是協議,端口(若是指定了)和主機對於兩個頁面是相同的,則兩個頁面具備相同的源,也就是同源。也就是說,要同時知足如下3個條件,才能叫同源:ajax

  1. 協議相同
  2. 端口相同
  3. 主機相同

舉個例子就一目瞭然了:json

咱們來看下面的頁面是否與 http://store.company.com/dir/index.html 是同源的?segmentfault

  1. http://store.company.com/dir/index2.html 同源
  2. http://store.company.com/dir2/index3.html 同源 雖然在不一樣文件夾下
  3. https://store.company.com/secure.html 不一樣源 不一樣的協議(https)
  4. http://store.company.com:81/dir/index.html 不一樣源 不一樣的端口(81)
  5. http://news.company.com/dir/other.html 不一樣源 不一樣的主機(news)

因此當面對跨域問題的時候,有什麼解決方案呢?跨域

跨域的幾種解決方案

document.domain方法

咱們來看一個具體場景:有一個頁面 http://www.example.com/a.html ,它裏面有一個iframe,這個iframe的源是 http://example.com/b.html ,很顯然它們是不一樣源的,因此咱們沒法在父頁面中操控子頁面的內容。dom

解決方案以下:異步

<!-- b.html -->
<script>
document.domain = 'example.com';
</script>
<!-- a.html -->
<script>
document.domain = 'example.com';
var iframe = document.getElementById('iframe').contentWindow.document;

//後面就能夠操做iframe裏的內容了...

</script>

因此咱們只要將兩個頁面的document.domain設置成一致就能夠了,要注意的是,document.domain的設置是有限制的,咱們只能把document.domain設置成自身或更高一級的父域。函數

可是,這種方法只能解決主域相同的跨域問題。post

window.name方法

window對象有個name屬性,該屬性有個特徵:即在一個窗口(window)的生命週期內,窗口載入的全部的頁面都是共享一個window.name的,每一個頁面對window.name都有讀寫的權限,window.name是持久存在一個窗口載入過的全部頁面中的,並不會因新頁面的載入而進行重置。

咱們來看一個具體場景,在一個頁面 example.com/a.html 中,咱們想獲取 data.com/data.html 中的數據,如下是解決方案:

<!-- data.html -->
<script>
window.name = 'data'; //這是就是咱們須要通訊的數據
</script>
<!-- a.html -->
<html>
<head>
<script>
    function getData () {
        var iframe = document.getElementById('iframe');
        iframe.src = 'example.com/b.html'; // 這裏讓iframe與父頁面同源
        
        iframe.onload = function () {
            var data = iframe.contentWindow.name; //在這裏咱們獲得了跨域頁面中傳來的數據
        };
    }
</script>
</head>
<body>
</body>
</html>

JSONP方法

JONSP(JSON with Padding)是JSON的一種使用模式。基本原理以下:

<!-- a.html -->
<script>
    function dealData (data) {
        console.log(data);
    }
</script>

<script src='http://example.com/data.php?callback=dealData'></script>
<?php
    $callback = $_GET['callback'];
    $data = 'data';
    echo $callback.'('.json_encode($data).')';
?>

這時候在a.html中咱們獲得了一條js的執行語句dealData('data'),從而達到了跨域的目的。

因此JSONP的原理其實就是利用引入script不限制源的特色,把處理函數名做爲參數傳入,而後返回執行語句,仔細閱讀以上代碼就能夠明白裏面的意思了。

若是在jQuery中用JSONP的話就更加簡單了:

<script>
$.getJSON(''http://example.com/data.php?callback=?', function (data) {
    console.log(data);
});
</script>

注意jQuery會自動生成一個全局函數來替換callback=?中的問號,以後獲取到數據後又會自動銷燬,實際上就是起一個臨時代理函數的做用。$.getJSON方法會自動判斷是否跨域,不跨域的話,就調用普通的ajax方法;跨域的話,則會以異步加載js文件的形式來調用JSONP的回調函數。

總結

除了上述方法外,HTML5還新增了一個window.postMessage()方法,有興趣的能夠自行查閱。

最後,解決跨域問題還有一個更通用更強大的CORS方法,我單獨把它拿出來總結了一篇文章:跨域問題的根本解決方案CORS

相關文章
相關標籤/搜索