經常使用跨域方法實踐(一)

這幾天看了鬼道師兄的《跨終端Web》這本書,該書從解決實際業務出發,講述了跨終端的優點與將來,受益良多。其中,書中第九章介紹了做者在阿里內部的一個參賽做品Storage,該做品巧妙的使用了跨域知識,讓我見識到跨域其實不單單是JSONP。之前,對前端跨域這塊或多或少有點了解,但真正動手實踐的不是不少。因而,這段時間我好好整理了經常使用跨域方法的具體實現。本文,主要介紹了JSONPCORS的實現方式。javascript

相關概念:html

  • 只要協議、域名、端口有任何一個不一樣,都被看成是不一樣的域
  • JavaScript出於安全方面的考慮,不容許跨域調用其餘頁面的對象
  • 跨域簡單地理解就是由於JavaScript同源策略的限制,a.com域名下的js沒法操做b.com或是c.a.com域名下的對象

注意:前端

  • 若是是協議和端口形成的跨域問題「前臺」是無能爲力的
  • 在跨域問題上,域僅僅是經過「URL的首部」來識別而不會去嘗試判斷相同的ip地址對應着兩個域或兩個域是否在同一個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基於NodeJSExpress4.X框架,且端口設置爲80java

JSONP

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-test跨域

JSONP優缺點:

  • 優勢:它不像XMLHttpRequest對象實現的Ajax請求那樣受到同源策略的限制;它的兼容性更好,在更加古老的瀏覽器中均可以運行;而且在請求完畢後能夠經過調用callback的方式回傳結果
  • 缺點:它只支持GET請求而不支持POST等其它類型的HTTP請求;它只支持跨域HTTP請求這種狀況,不能解決不一樣域的兩個頁面之間如何進行JS調用的問題

CORS

CORS(Cross-Origin Resource Sharing)跨域資源共享,定義了必須在訪問跨域資源時,瀏覽器與服務器應該如何溝通。

跨域原理:CORS背後的基本思想就是使用自定義的HTTP頭部讓瀏覽器與服務器進行溝通,從而決定請求或響應是應該成功仍是失敗

瀏覽器支持狀況:

  • Chrome 3+
  • Firefox 3.5+
  • Opera 12+
  • Safari 4+
  • Internet Explorer 8+

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-test

CORS優缺點:

  • 優勢:支持全部類型的HTTP請求;使用普通的XMLHttpRequest發起請求和得到數據,擁有良好的出錯處理
  • 缺點:老式瀏覽器不支持

結語

測試源碼請戳這!下面一篇文章將介紹document.domainURL.hashcross-fragmentwindow.namepostMessage這五種方式的跨域實現。

參考

相關文章
相關標籤/搜索