浏览器跨域访问解决方案
瀏覽器跨域訪問解決方案
2015年11月4日?18972次瀏覽跨域的概念
跨域大家都知道,不同地址,不同端口,不同級別,不同協議都會構成跨域。例如:about.haorooms.com和www.haorooms.com都會構成跨域。總結起來只要協議、域名、端口有任何一個不同,都被當作是不同的域。下面舉例,每兩個一組。
URL 說明 是否允許通信 http://www.haorooms.com/a.js http://www.haorooms.com/b.js 同一域名下 允許 http://www.haorooms.com/lab/a.js http://www.haorooms.com/script/b.js 同一域名下不同文件夾 允許 http://www.haorooms.com:8000/a.js http://www.haorooms.com/b.js 同一域名,不同端口 不允許 http://www.haorooms.com/a.js https://www.haorooms.com/b.js 同一域名,不同協議 不允許 http://www.haorooms.com/a.js http://60.32.92.74/b.js 域名和域名對應ip 不允許 http://www.haorooms.com/a.js http://about.haorooms.com/b.js 主域相同,子域不同 不允許 http://www.haorooms.com/a.js http://haorooms.com/b.js 同一域名,不同二級域名(同上) 不允許(cookie這種情況下也不允許訪問) http://www.hao123.com/a.js http://www.haorooms.com/b.js 不同域名 不允許解決跨域的方案
上一篇文章,我寫了window.postMessage,是一種跨域的解決方案。今天再介紹幾個。
CORS跨域資源共享
眾所周知,我們之前跨域很多時候用的是jsonp的方式,jsonp的方式我后面介紹。下面說說CORS跨域和jsonp跨域的優勢:
CORS與JSONP相比,無疑更為先進、方便和可靠。
1、 JSONP只能實現GET請求,而CORS支持所有類型的HTTP請求。
2、 使用CORS,開發者可以使用普通的XMLHttpRequest發起請求和獲得數據,比起JSONP有更好的錯誤處理。
3、 JSONP主要被老的瀏覽器支持,它們往往不支持CORS,而絕大多數現代瀏覽器都已經支持了CORS。[低版本IE7以下不支持,要支持IE7還是要用jsonp方式]
CORS的使用
CORS要前后端同時做配置。
1、首先我們來看前端。
純js的ajax請求。
<script type="text/javascript"> var xhr = new XMLHttpRequest(); //ie6以下用new ActiveXObject("Microsoft.XMLHTTP");可以做能力判斷。 xhr.open("GET", "/haorooms",true); xhr.send(); </script>以上的haorooms是相對路徑,如果我們要使用CORS,相關Ajax代碼可能如下所示:
<script type="text/javascript"> var xhr = new XMLHttpRequest();//ie6以下用new ActiveXObject("Microsoft.XMLHTTP");可以做能力判斷。 xhr.open("GET", "http://www.haorooms.com/CORS",true); xhr.send(); </script>當然,你也可以用jquery的ajax進行。
2、后端或者服務器端的配置
下面我們主要介紹Apache和PHP里的設置方法。
Apache:Apache需要使用mod_headers模塊來激活HTTP頭的設置,它默認是激活的。你只需要在Apache配置文件的 < Directory >, < Location>, < Files >或< VirtualHost>的配置里加入以下內容即可:
Header set Access-Control-Allow-Origin *PHP:只需要使用如下的代碼設置即可。
<?php header("Access-Control-Allow-Origin:*");以上的配置的含義是允許任何域發起的請求都可以獲取當前服務器的數據。當然,這樣有很大的危險性,惡意站點可能通過XSS攻擊我們的服務器。所以我們應該盡量有針對性的對限制安全的來源,例如下面的設置使得只有www.haorooms.com這個域才能跨域訪問服務器的API。
Access-Control-Allow-Origin: http://www.haorooms.com通過jsonp跨域
jsonp跨域也需要前后端配合使用。一般后端設置callback ,前端給后臺接口中傳一個callback 就可以。
例如前端代碼:
<script type="text/javascript"> function dosomething(jsondata){ //處理獲得的json數據 } </script> <script src="http://haorooms.com/data.php?callback=dosomething"></script>后臺代碼:
<?php $callback = $_GET['callback'];//得到回調函數名 $data = array('a','b','c');//要返回的數據 echo $callback.'('.json_encode($data).')';//輸出 ?>假如你用ajax方式進行jsonp跨域,我之前的一篇文章中提及過:http://www.haorooms.com/post/jquery_ajax_wg
/* //簡寫形式,效果相同 $.getJSON("url跨域地址", {參數,要把callback作為參數傳到后端},function(data){ //結構處理 },"jsonp"); */ $.ajax({ type : "get", url : "跨域地址", dataType : "jsonp",//數據類型為jsonp jsonp: "callback",//服務端用于接收callback調用的function名的參數【后臺接受什么參數,我們就傳什么參數】我們上面設置是callback success : function(data){ //結果處理 }, error:function(data){ console.log(data); } });通過修改document.domain來跨子域
我們只需要在跨域的兩個頁面中設置document.domain就可以了。修改document.domain的方法只適用于不同子域的框架間的交互。
例如:1.在頁面 http:// www.haorooms.com/a.html 中設置document.domain
<iframe id = "iframe" src="http://haorooms.com/b.html" onload = "test()"></iframe> <script type="text/javascript"> document.domain = 'haorooms.com';//設置成主域 function test(){ alert(document.getElementById('iframe').contentWindow);//contentWindow 可取得子窗口的 window 對象 } </script>2、在頁面http:// haorooms.com/b.html 中設置document.domain
<script type="text/javascript"> document.domain = 'haorooms.com';//在iframe載入這個頁面也設置document.domain,使之與主頁面的document.domain相同 </script>使用window.name來進行跨域
原理:
window對象有個name屬性,該屬性有個特征:即在一個窗口(window)的生命周期內,窗口載入的所有的頁面都是共享一個window.name的,每個頁面對window.name都有讀寫的權限,window.name是持久存在一個窗口載入過的所有頁面中的。
方法:
假如有三個頁面。
a.com/app.html:應用頁面。 a.com/proxy.html:代理文件,一般是一個沒有任何內容的html文件,需要和應用頁面在同一域下。 b.com/data.html:應用頁面需要獲取數據的頁面,可稱為數據頁面。1、在應用頁面(a.com/app.html)中創建一個iframe,把其src指向數據頁面(b.com/data.html)。
數據頁面會把數據附加到這個iframe的window.name上,data.html代碼如下:
<script type="text/javascript"> window.name = 'I was there!'; // 這里是要傳輸的數據,大小一般為2M,IE和firefox下可以大至32M左右 // 數據格式可以自定義,如json、字符串 </script>2、在應用頁面(a.com/app.html)中監聽iframe的onload事件,在此事件中設置這個iframe的src指向本地域的代理文件(代理文件和應用頁面在同一域下,所以可以相互通信)。
app.html部分代碼如下:
<script type="text/javascript"> var state = 0, iframe = document.createElement('iframe'), loadfn = function() { if (state === 1) { var data = iframe.contentWindow.name; // 讀取數據 alert(data); //彈出'I was there!' } else if (state === 0) { state = 1; iframe.contentWindow.location = "http://a.com/proxy.html"; // 設置的代理文件 } }; iframe.src = 'http://b.com/data.html'; if (iframe.attachEvent) { iframe.attachEvent('onload', loadfn); } else { iframe.onload = loadfn; } document.body.appendChild(iframe); </script>3、獲取數據以后銷毀這個iframe,釋放內存;這也保證了安全(不被其他域frame js訪問)。
<script type="text/javascript"> iframe.contentWindow.document.write(''); iframe.contentWindow.close(); document.body.removeChild(iframe); </script>使用HTML5的window.postMessage方法跨域
轉載于:https://www.cnblogs.com/libaoli/p/7879434.html
總結
以上是生活随笔為你收集整理的浏览器跨域访问解决方案的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 实现图片打乱_2020 回顾 | 25张
- 下一篇: java8编程入门 pdf_Java8编