js跨域解决方式
什么是跨域?
概念:僅僅要協議、域名、port有不論什么一個不同,都被當作是不同的域。(所謂同源是指,域名。協議,port同樣。),對于port和協議的不同,僅僅能通過后臺來解決。
URL 說明 是否同意通信 http://www.a.com/a.js http://www.a.com/b.js 同一域名下 同意 http://www.a.com/lab/a.js http://www.a.com/script/b.js 同一域名下不同目錄 同意 http://www.a.com:8000/a.js http://www.a.com/b.js 同一域名,不同port 不同意 http://www.a.com/a.js https://www.a.com/b.js 同一域名,不同協議 不同意 http://www.a.com/a.js http://70.32.92.74/b.js 域名和域名相應ip 不同意 http://www.a.com/a.js http://script.a.com/b.js 主域同樣,子域不同 不同意 http://www.a.com/a.js http://a.com/b.js 同一域名。不同二級域名(同上) 不同意(cookie這樣的情況下也不同意訪問) http://www.cnblogs.com/a.js http://www.a.com/b.js 不同域名 不同意
1、跨域資源共享(CORS)
CORS(Cross-Origin Resource Sharing)跨域資源共享,定義了必須在訪問跨域資源時,瀏覽器與server應該怎樣溝通。
CORS背后的基本思想就是使用自己定義的HTTP頭部讓瀏覽器與server進行溝通。從而決定請求或響應是應該成功還是失敗。
server端對于CORS的支持。主要就是通過設置Access-Control-Allow-Origin來進行的。
假設瀏覽器檢測到對應的設置。就能夠同意Ajax進行跨域的訪問。
比如:客戶端的域名是www.client.com,而請求的域名是www.server.com
在被請求的Response header中增加
[php]?view plain?copy ?
就能夠實現ajax POST跨域訪問了。
代碼例如以下:
client.html?路徑:http://www.client.com/client.html
[html]?view plain?copy ?
server.php?路徑:http://www.server.com/server.php
[php]?view plain?copy ?
?
$_POST['gender']?:?''??Access-Control-Allow-Origin:*?表示同意不論什么域名跨域訪問
假設須要指定某域名才同意跨域訪問,僅僅需把Access-Control-Allow-Origin:*改為Access-Control-Allow-Origin:同意的域名
比如:header('Access-Control-Allow-Origin:http://www.client.com');
假設須要設置多個域名同意訪問。這里須要用php處理一下
比如同意 www.client.com 與 www.client2.com 能夠跨域訪問
server.php 改動為
[php]?view plain?copy ?
php??
?
$_POST['name']?:?'',??要解決跨域的問題。我們能夠使用下面幾種方法:
2、通過jsonp跨域
如今問題來了?什么是jsonp?維基百科的定義是:JSONP(JSON with Padding)是資料格式?JSON?的一種“使用模式”,能夠讓網頁從別的網域要資料。
JSONP也叫填充式JSON,是應用JSON的一種新方法。僅僅只是是被包括在函數調用中的JSON。比如:
callback({"name","trigkit4"});JSONP由兩部分組成:回調函數和數據。
回調函數是當響應到來時應該在頁面中調用的函數,而數據就是傳入回調函數中的JSON數據。
在js中,我們直接用XMLHttpRequest請求不同域上的數據時,是不能夠的。可是,在頁面上引入不同域上的js腳本文件卻是能夠的,jsonp正是利用這個特性來實現的。
?比如:
<script type="text/javascript">function dosomething(jsondata){//處理獲得的json數據} </script> <script src="http://example.com/data.php?callback=dosomething"
></script>js文件加載成功后會運行我們在url參數中指定的函數,而且會把我們須要的json數據作為參數傳入。
所以jsonp是須要server端的頁面進行對應的配合的。
<?php $callback = $_GET['callback'];//得到回調函數名 $data = array('a','b','c');//要返回的數據 echo $callback.'('.json_encode($data).')';//輸出 ?>終于。輸出結果為:dosomething(['a','b','c']);
假設你的頁面使用jquery,那么通過它封裝的方法就能非常方便的來進行jsonp操作了。
<script type="text/javascript"> $.getJSON('http://example.com/data.php?callback=?,function(jsondata)'
){ //處理獲得的json數據 }); </script>jquery會自己主動生成一個全局函數來替換callback=?
中的問號,之后獲取到數據后又會自己主動銷毀,實際上就是起一個暫時代理函數的作用。$.getJSON方法會自己主動推斷是否跨域,不跨域的話,就調用普通的ajax方法;跨域的話,則會以異步載入js文件的形式來調用jsonp的回調函數。
JSONP的優缺點
JSONP的長處是:它不像XMLHttpRequest對象實現的Ajax請求那樣受到同源策略的限制;它的兼容性更好,在更加古老的瀏覽器中都能夠執行。不須要XMLHttpRequest或ActiveX的支持;而且在請求完成后能夠通過調用callback的方式回傳結果。
JSONP的缺點則是:它僅僅支持GET請求而不支持POST等其他類型的HTTP請求。它僅僅支持跨域HTTP請求這樣的情況,不能解決不同域的兩個頁面之間怎樣進行JavaScript調用的問題。
CORS和JSONP對照
CORS與JSONP相比,無疑更為先進、方便和可靠。
1、 JSONP僅僅能實現GET請求,而CORS支持全部類型的HTTP請求。2、
使用CORS,開發人員能夠使用普通的XMLHttpRequest發起請求和獲得數據。比起JSONP有更好的錯誤處理。3、 JSONP主要被老的瀏覽器支持,它們往往不支持CORS,而絕大多數現代瀏覽器都已經支持了CORS)。
3、通過改動document.domain來跨子域
瀏覽器都有一個同源策略,其限制之中的一個就是第一種方法中我們說的不能通過ajax的方法去請求不同源中的文檔。 它的第二個限制是瀏覽器中不同域的框架之間是不能進行js的交互操作的。
不同的框架之間是能夠獲取window對象的。但卻無法獲取對應的屬性和方法。比方,有一個頁面,它的地址是http://www.example.com/a.html?, 在這個頁面里面有一個iframe,它的src是http://example.com/b.html, 非常顯然,這個頁面與它里面的iframe框架是不同域的,所以我們是無法通過在頁面中書寫js代碼來獲取iframe中的東西的:
這個時候,document.domain就能夠派上用場了,我們僅僅要把http://www.example.com/a.html?和http://example.com/b.html這兩個頁面的document.domain都設成同樣的域名就能夠了。但要注意的是。document.domain的設置是有限制的,我們僅僅能把document.domain設置成自身或更高一級的父域,且主域必須同樣。
(1).在頁面?http://www.example.com/a.html?中設置document.domain:
<iframe id = "iframe" src="http://example.com/b.html" onload = "test()"></iframe> <script type="text/javascript">document.domain = 'example.com';//設置成主域function test(){alert(document.getElementById('iframe').contentWindow);//contentWindow 可取得子窗體的 window 對象} </script>(2).在頁面?http://example.com/b.html?中也設置document.domain:
<script type="text/javascript">document.domain = 'example.com';//在iframe加載這個頁面也設置document.domain,使之與主頁面的document.domain同樣 </script>改動document.domain的方法僅僅適用于不同子域的框架間的交互。
4、使用window.name來進行跨域
window對象有個name屬性。該屬性有個特征:即在一個窗體(window)的生命周期內,窗體加載的全部的頁面都是共享一個window.name的,每一個頁面對window.name都有讀寫的權限,window.name是持久存在一個窗體加載過的全部頁面中的。
樣例:
特將詳細實現方法記錄例如以下:
如a.com站點想通過JS獲取b.com站點的數據。
(1) 在a.com站點加入一個空HTML頁。
名稱為:http://a.com/null.html
(2) 在a.com站點須要獲取數據頁面(如:http://a.com/getDomainData.html)內容例如以下:
| <!DOCTYPE?html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> <html?xmlns="http://www.w3.org/1999/xhtml" > <head> ????<title>跨域獲取數據</title> ????<script?type="text/javascript"> ????function domainData(url, fn) ????{ ????????var isFirst = true; ????????var iframe = document.createElement('iframe'); ????????iframe.style.display = 'none'; ????????var loadfn = function(){ ????????????if(isFirst){ ????????????????iframe.contentWindow.location = 'http://a.com/null.html'; ????????????????isFirst = false; ????????????} else { ????????????????fn(iframe.contentWindow.name); ????????????????iframe.contentWindow.document.write(''); ????????????????iframe.contentWindow.close(); ????????????????document.body.removeChild(iframe); ????????????????iframe.src = ''; ????????????????iframe = null; ????????????} ????????}; ????????iframe.src = url; ????????if(iframe.attachEvent){ ????????????iframe.attachEvent('onload', loadfn); ????????} else { ????????????iframe.onload = loadfn; ????????} ????????? ????????document.body.appendChild(iframe); ????} ????</script> </head> <body> </body> ????<script?type="text/javascript"> ????domainData('http://b.com/data.html', function(data){ ????????alert(data); ????}); ????</script> </html> |
(3) 在b.com中加入獲取數據頁面 如:http://b.com/data.html 內容需包括:?
| <script> window.name = '須要跨域傳遞的數據'; </script> |
(4) 訪問 http://a.com/getDomainData.html 就可返回?http://b.com/data.html 中的window.name中的數據了。
須要注意的地方
null.html 是必須的。內容可為空。
?iframe的onload事件綁定 必須這樣寫:
| if(iframe.attachEvent){ ?????iframe.attachEvent('onload', loadfn); }else?{ ?????iframe.onload = loadfn; } |
調用domainData函數必須在body后面,或頁面載入完后。
調用時會運行?http://b.com/data.html 頁面的腳本。
?
5、使用HTML5的window.postMessage方法跨域
window.postMessage(message,targetOrigin)?方法是html5新引進的特性,能夠使用它來向其他的window對象發送消息。不管這個window對象是屬于同源或不同源,眼下IE8+、FireFox、Chrome、Opera等瀏覽器都已經支持window.postMessage方法。
?
轉載于:https://www.cnblogs.com/brucemengbm/p/7363746.html
總結
- 上一篇: ASP.NET Core - Razor
- 下一篇: 360极速浏览器无法正确getHours