這幾天看了鬼道師兄的《跨終端Web》這本書,該書從解決實際業務出發,講述了跨終端的優點與將來,受益良多。其中,書中第九章介紹了做者在阿里內部的一個參賽做品Storage,該做品巧妙的使用了跨域知識,讓我見識到跨域其實不單單是
JSONP
。之前,對前端跨域這塊或多或少有點了解,但真正動手實踐的不是不少。因而,這段時間我好好整理了經常使用跨域方法的具體實現。本文,主要介紹了JSONP
和CORS
的實現方式。javascript
相關概念:html
a.com
域名下的js沒法操做b.com
或是c.a.com
域名下的對象注意:前端
ip
上(「URL的首部」指window.location.protocol +window.location.host
,也能夠理解爲「Domains, protocols and ports must match」)相關配置:爲了演示效果,在hosts文件裏面添加以下內容html5
127.0.0.1 www.myapp.com 127.0.0.1 sample.myapp.com 127.0.0.1 www.otherapp.com
注意:測試demo基於NodeJS
的Express4.X
框架,且端口設置爲80
java
JSONP
也叫填充式JSON
,是應用JSON
的一種新方法,只不過是被包含在函數調用中的JSON
(如:callback({"name", "chenjun"});
)。JSONP
由兩部分組成:回調函數和數據。回調函數是當響應到來時應該在頁面中調用的函數,而數據就是傳入回調函數中的JSON
數據git
跨域原理:利用<script>
標籤沒有跨域限制,實現跨域目的github
訪問頁面:jsonp_test.ejsjson
<script>
function dosomething(jsondata) { alert(jsondata.name + " " + jsondata.age); } </script> <script src="http://www.otherapp.com/jsonp_data?callback=dosomething"></script>
後臺路由:index.jssegmentfault
/* JSONP Test */ router.get('/jsonp_test', function(req, res) { res.render('jsonp/jsonp_test'); }); router.get('/jsonp_data', function(req, res) { var callback = req.query.callback; var data = { name: "chenjun", age: "25" }; var str = callback + '(' + JSON.stringify(data) + ')'; //jsonp res.end(str); });
效果:跨域
JSONP優缺點:
XMLHttpRequest
對象實現的Ajax請求那樣受到同源策略的限制;它的兼容性更好,在更加古老的瀏覽器中均可以運行;而且在請求完畢後能夠經過調用callback的方式回傳結果GET
請求而不支持POST
等其它類型的HTTP請求;它只支持跨域HTTP請求這種狀況,不能解決不一樣域的兩個頁面之間如何進行JS調用的問題CORS
(Cross-Origin Resource Sharing)跨域資源共享,定義了必須在訪問跨域資源時,瀏覽器與服務器應該如何溝通。
跨域原理:CORS
背後的基本思想就是使用自定義的HTTP頭部讓瀏覽器與服務器進行溝通,從而決定請求或響應是應該成功仍是失敗
瀏覽器支持狀況:
Chrome,Firefox,Opera和Safari都使用XMLHttpRequest2
對象。 Internet Explorer使用了相似的XDomainRequest
對象,其工做原理和XMLHttpRequest
大體相同,但增長了額外的安全預防措施。
訪問頁面:cors_test.ejs
// 建立XHR 對象. function createCORSRequest(method, url) { var xhr = new XMLHttpRequest(); if ("withCredentials" in xhr) { // XHR for Chrome/Firefox/Opera/Safari. xhr.open(method, url, true); } else if (typeof XDomainRequest != "undefined") { // XDomainRequest for IE. xhr = new XDomainRequest(); xhr.open(method, url); } else { // 不支持CORS. xhr = null; } return xhr; } // 發起CORS請求 function makeCorsRequest() { var url = 'http://www.otherapp.com/cors_data'; var xhr = createCORSRequest('GET', url); if (!xhr) { alert('CORS not supported!'); return; } // 響應處理 xhr.onload = function() { var text = xhr.responseText; alert(text); } xhr.onerror = function() { alert('Woops, there was an error making the request.'); } xhr.send(); } makeCorsRequest();
後臺路由:index.js
/* CORS Test */ router.get('/cors_test', function(req, res) { res.render('cors/cors_test'); }); router.get('/cors_data', function(req, res) { var data = { name: "chenjun", age: "25" }; // 設置響應頭 res.setHead('Access-Control-Allow-Origin', '*'); res.end(JSON.stringify(data)); });
效果:
CORS優缺點:
測試源碼請戳這!下面一篇文章將介紹document.domain
、URL.hash
、cross-fragment
、window.name
和postMessage
這五種方式的跨域實現。