1. 程式人生 > >同源策略、跨域、json和jsonp

同源策略、跨域、json和jsonp

open 是把 tro 兩個 屬性 ont type cti 結果

同源策略

源(origin)就是協議、域名和端口號。若地址裏面的協議、域名和端口號均相同則屬於同源。

以下是相對於 http://www.a.com/test/index.html 的同源檢測
  ? http://www.a.com/dir/page.html ----成功
  ? http://www.child.a.com/test/index.html ----失敗,域名不同
  ? https://www.a.com/test/index.html ----失敗,協議不同
  ? http://www.a.com:8080/test/index.html ----失敗,端口號不同

同源策略是瀏覽器的一個安全功能,不同源的客戶端腳本在沒有明確授權的情況下,不能讀寫對方資源

。所以a.com下的js腳本采用ajax讀取b.com裏面的文件數據是會報錯的。

跨域

1、什麽是跨域

受前面所講的瀏覽器同源策略的影響,不是同源的腳本不能操作其他源下面的對象。想要操作另一個源下的對象是就需要跨域。

2、跨域的實現方式

(1)降域 document.domain

同源策略認為域和子域屬於不同的域,如:child1.a.com 與 a.com,child1.a.com 與 child2.a.com,xxx.child1.a.com 與 child1.a.com

兩兩不同源,可以通過設置 document.damain=‘a.com‘,瀏覽器就會認為它們都是同一個源。想要實現以上任意兩個頁面之間的通信,兩個頁面必須都設置documen.damain=‘a.com‘。

此方式的特點:

1. 只能在父域名與子域名之間使用,且將 xxx.child1.a.com域名設置為a.com後,不能再設置成child1.a.com。

2. 存在安全性問題,當一個站點被攻擊後,另一個站點會引起安全漏洞。3. 這種方法只適用於 Cookie 和 iframe 窗口。

(2)JSONP跨域

采用jsonp跨域也存在問題:
1. 使用這種方法,只要是個網站都可以拿到b.com裏的數據,存在安全性問題。需要網站雙方商議基礎token的身份驗證。
2. 只能是GET,不能POST。
3. 可能被註入惡意代碼,篡改頁面內容,可以采用字符串過濾來規避此問題。

(3)CORS

CORS是一個W3C標準,全稱是"跨域資源共享"(Cross-origin resource sharing)。它允許瀏覽器向跨源服務器,發出XMLHttpRequest請求,從而克服了AJAX只能同源使用的限制。剛才的例子中,在b.com裏面添加響應頭聲明允許a.com的訪問,代碼:Access-Control-Allow-Origin: http://a.com然後a.com就可以用ajax獲取b.com裏的數據了。

(4)其它方法

1. HTML5的postMessage方法
2. window.name
3. location.hash

json和jsonp

  • JSON是一種基於文本的數據交換方式(不支持跨域),或者叫做數據描述格式,是數組和對象的嵌套,而JSONP是一種非官方跨域數據交互協議。簡單地使用json並不能支持跨域資源請求,為了解決這個問題,需要采用jsonp數據交互協議。
  • 同源下的前後端數據交換格式確定使用json了,如果想獲取別人網站上提供的數據怎麽做到呢?也就是跨域讀取數據問題,json是不行的,因為json只是普通的文本格式,能讓你這樣就輕松拿到那服務端就沒有任何安全和保密性可言了,所以瀏覽器使用了同源策略來限制文件獲取。最後的結果就是只有像img、script、iframe這類可以指定src屬性的標簽有跨域獲取別人網站上數據(圖片,腳本,源文件其實都是數據)的能力。比如:
    <img src="http://img30.360buyimg.com/jgsq-productsoa/jfs/t2407/323/1635505465/47386/f2d89d88/56615e00N7a475ee6.jpg" />
    
    <script src="http://apps.bdimg.com/libs/jquery/2.1.4/jquery.min.js"></script>
  • 然而,眾所周知,js文件的調用不受跨域與否的限制,因此如果想通過純web端跨域訪問數據,只能在遠程服務器上設法將json數據封裝進js格式的文件中,供客戶端調用和進一步處理,這就是jsonp協議的原理。該協議的一個要點就是允許用戶傳遞一個callback參數給服務端,然後服務端返回數據時會將這個callback參數作為函數名來包裹住JSON數據,這樣客戶端就可以隨意定制自己的函數來自動處理返回數據了
  • 簡單的說,就是json不支持跨域,而js可以跨域,因此在服務器端用客戶端提供的js函數名將json數據封裝起來,再將函數提供給客戶端調用,從而獲得json數據。開發過程中,如果出現類似 “Origin ****** is not allowed by Access-Control-Allow-Origin.” 的錯誤,則可能是由於json數據不支持跨域導致的,應考慮使用jsonp協議。如果出現類似 ”SyntaxError: Unexpected token ‘:‘. Parse error.“ 的錯誤,則可能是由於返回的json數據沒有用”callback“傳遞的函數名封裝導致的。

    例如:網站A需要獲取網站B的數據,網站B說我給你們一個方法:

    1. 你們使用<script src="http://www.B.com/open.js"></script>標簽先獲取到open.js文件(網站B的責任),這裏邊有你們需要的數據。

    2. 你們獲取數據後處理數據的方法名必須命名為foo(數據請求者的責任和義務)

    這裏相當於B網站和請求獲取數據者之間建立了一個協議,要求請求者務必按照規則辦事,如果請求者不能同時遵守上面兩條就不能按預期獲取數據。

  • jsonp全名叫做json with padding,很形象,就是把json對象用符合js語法的形式包裹起來以使其它網站可以請求得到,也就是將json數據封裝成js文件;
  • json是理想的數據交換格式,但沒辦法跨域直接獲取,於是就將json包裹(padding)在一個合法的js語句中作為js文件傳過去。這就是json和jsonp的區別,json是想要的東西,jsonp是達到這個目的而普遍采用的一種方法,當然最終獲得和處理的還是json。所以說json是目的,jsonp只是手段。json總會用到,而jsonp只有在跨域獲取數據才會用到。
  • 理解了json和jsonp的區別之後,其實ajax裏的跨域獲取數據就很好理解和實現了,同源時候並沒有什麽特別的,直接取就行,跨域時候需要拐個彎來達到目的。
  • 附上jquery中ajax請求json數據實例:
    //同源
    $.ajax({
        url:"persons.json",
        success:function(data){
    console.log(data);
     //ToDo..
    }
    });
    
    //跨域
    $.ajax({
        url:"http://www.B.com/open.php?callback=?",
        dataType:"jsonp",
        success:function(data){
            console.log(data);
            //ToDo..
        }
    }); 

同源策略、跨域、json和jsonp