您好,登錄后才能下訂單哦!
小編給大家分享一下ajax如何解決跨域問題,相信大部分人都還不怎么了解,因此分享這篇文章給大家參考一下,希望大家閱讀完這篇文章后大有收獲,下面讓我們一起去了解一下吧!
跨域
同源策略限制
同源策略阻止從一個域上加載的腳本獲取或操作另一個域上的文檔屬性。也就是說,受到請求的 URL 的域必須與當前 Web 頁面的域相同。這意味著瀏覽器隔離來自不同源的內容,以防止它們之間的操作。
解決方式
通常來說,比較通用的有如下兩種方式,一種是從服務器端下手,另一種則是從客戶端的角度出發。二者各有利弊,具體要使用哪種方式還需要具體的分析。
服務器設置響應頭
服務器代理
客戶端采用腳本回調機制。
方式一
Access-Control-Allow-Origin 關鍵字只有在服務器端進行設置才
會生效。也就是說即使再客戶端使用
xmlhttprequest.setHeaderREquest('xx','xx');
也不會有什么效果。
正常ajax請求
下面來模擬一下ajax非跨域請求的案例實現。
test1.html
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>ajax 測試</title> </head> <body> <input type="button" value="Test" onclick="crossDomainRequest()"> <div id="content"></div> <script> var xhr = new XMLHttpRequest(); var url = 'http://localhost/learn/ajax/test1.php'; function crossDomainRequest() { document.getElementById('content').innerHTML = "<font color='red'>loading...</font>"; // 延遲執行 setTimeout(function () { if (xhr) { xhr.open('GEt', url, true); xhr.onreadystatechange = handle_response; xhr.send(null); } else { document.getElementById('content').innerText = "不能創建XMLHttpRequest對象"; } }, 3000); } function handle_response() { var container = document.getElementById('content'); if (xhr.readyState == 4) { if (xhr.status == 200 || xhr.status == 304) { container.innerHTML = xhr.responseText; } else { container.innerText = '不能跨域請求'; } } } </script> </body> </html>
同級目錄下的test1.PHP內容如下:
<?php echo "It Works."; ?>
跨域請求
剛才是HTML文件和php文件都在Apache的容器下,所以沒有出現跨域的情形,現在把HTML文件放到桌面上,這樣再次請求PHP數據的話,就營造了這樣一個“跨域請求”了。
注意看瀏覽器的地址欄信息
再次進行訪問,發現會出現下面的錯誤信息。
針對這種情況,比較常見的一個操作就是設置Access-Control-Allow-Origin。
格式: Access-Control-Allow-Origin: domain.com/xx/yy.*
如果知道客戶端的域名或者請求的固定路徑,則最好是不使用通配符的方式,來進一步保證安全性。如果不確定,那就是用*通配符好了。
后端開發語言為PHP的時候可以再文件開始處這么設置:
header("Access-Control-Allow-Origin: *");
如果是ASPX頁面的話,要這么設置(Java與之類似):
Response.AddHeader("Access-Control-Allow-Origin", "*");
這時,再次來訪問一下剛才的路徑。
服務器代理模式
這種方式應該算是比較常用的,而且被廣泛采納的一個方式了。說代理有點太過于書面化了,其實就是傳話兒的。來舉個小例子:
小明喜歡三班一個叫小紅的女孩兒,但是不好意思去要人家的QQ,微信號。然后就托和自己班的女生–小蘭。來幫自己去要。所以小蘭就相當于一個代理。幫助小明獲取原本不能直接獲取的小紅的聯系方式。
下面來舉個例子說明這個問題。
直接的跨域請求
修改一下剛才的URL即可,讓ajax直接去請求其他網站的數據。
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>ajax 測試</title> </head> <body> <input type="button" value="Test" onclick="crossDomainRequest()"> <div id="content"></div> <script> var xhr = new XMLHttpRequest(); // var url = 'http://localhost/learn/ajax/test1.php'; var url = 'http://api.qingyunke.com/api.php?key=free&appid=0&msg=%E5%93%92%E5%93%92'; function crossDomainRequest() { document.getElementById('content').innerHTML = "<font color='red'>loading...</font>"; // 延遲執行 setTimeout(function () { if (xhr) { xhr.open('GEt', url, true); xhr.onreadystatechange = handle_response; xhr.send(null); } else { document.getElementById('content').innerText = "不能創建XMLHttpRequest對象"; } }, 3000); } function handle_response() { var container = document.getElementById('content'); if (xhr.readyState == 4) { if (xhr.status == 200 || xhr.status == 304) { container.innerHTML = xhr.responseText; } else { container.innerText = '不能跨域請求'; } } } </script> </body> </html>
結果如下:
啟用代理模式
剛才的HTML頁面,咱們還是用自己的接口:
url = 'http://localhost/learn/ajax/test1.php';
具體如下:
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>ajax 測試</title> </head> <body> <input type="button" value="Test" onclick="crossDomainRequest()"> <div id="content"></div> <script> var xhr = new XMLHttpRequest(); var url = 'http://localhost/learn/ajax/test1.php'; // var url = 'http://api.qingyunke.com/api.php?key=free&appid=0&msg=%E5%93%92%E5%93%92'; function crossDomainRequest() { document.getElementById('content').innerHTML = "<font color='red'>loading...</font>"; // 延遲執行 setTimeout(function () { if (xhr) { xhr.open('GEt', url, true); xhr.onreadystatechange = handle_response; xhr.send(null); } else { document.getElementById('content').innerText = "不能創建XMLHttpRequest對象"; } }, 3000); } function handle_response() { var container = document.getElementById('content'); if (xhr.readyState == 4) { if (xhr.status == 200 || xhr.status == 304) { container.innerHTML = xhr.responseText; } else { container.innerText = '不能跨域請求'; } } } </script> </body> </html>
然后對應的test1.php應該幫助我們實現數據請求這個過程,把“小紅的聯系方式”要到手,并返回給“小明”。
<?php $url = 'http://api.qingyunke.com/api.php?key=free&appid=0&msg=hello%20world.'; $result = file_get_contents($url); echo $result; ?>
下面看下代碼執行的結果。
jsonp方式
JSONP(JSON with Padding) 靈感其實源于在HTML頁面中script標簽內容的加載,對于script的src屬性對應的內容,瀏覽器總是會對其進行加載。于是:
克服該限制更理想方法是在 Web 頁面中插入動態腳本元素,該頁面源指向其他域中的服務 URL 并且在自身腳本中獲取數據。腳本加載時它開始執行。該方法是可行的,因為同源策略不阻止動態腳本插入,并且將腳本看作是從提供 Web 頁面的域上加載的。但如果該腳本嘗試從另一個域上加載文檔,就不會成功。
實現的思路就是:
在服務器端組裝出客戶端預置好的json數據,通過回調的方式傳回給客戶端。
原生實現
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>ajax 測試</title> <script src="http://ajax.aspnetcdn.com/ajax/jquery/jquery-1.8.0.js" type="text/javascript"></script> </head> <body> <input type="text" name="talk" id="talk"> <input type="button" value="Test" id="btn"> <div id="content"></div> <script type="text/javascript"> function jsonpcallback(result) { for(var i in result) { alert(i+":"+result[i]); } } var JSONP = document.createElement("script"); JSONP.type='text/javascript'; JSONP.src='http://localhost/learn/ajax/test1.php?callback=jsonpcallback'; document.getElementsByTagName('head')[0].appendChild(JSONP); </script> </body> </html>
服務器端test1.php內容如下:
<?php $arr = [1,2,3,4,5,6]; $result = json_encode($arr); echo "jsonpcallback(".$result.")"; ?>
需要注意的是最后組裝的返回值內容。
來看下最終的代碼執行效果。
JQuery方式實現
采用原生的JavaScript需要處理的事情還是蠻多的,下面為了簡化操作,決定采用jQuery來代替一下。
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>ajax 測試</title> <script src="http://ajax.aspnetcdn.com/ajax/jquery/jquery-1.8.0.js" type="text/javascript"></script> </head> <body> <input type="text" name="talk" id="talk"> <input type="button" value="Test" id="btn"> <div id="content"></div> <script type="text/javascript"> function later_action(msg) { var element = $("<div><font color='green'>"+msg+"</font><br /></div>"); $("#content").append(element); } $("#btn").click(function(){ // alert($("#talk").val()); $.ajax({ url: 'http://localhost/learn/ajax/test1.php', method: 'post', dataType: 'jsonp', data: {"talk": $("#talk").val()}, jsonp: 'callback', success: function(callback){ console.log(callback.content); later_action(callback.content); }, error: function(err){ console.log(JSON.stringify(err)); }, }); }); </script> </body> </html>
相應的,test1.php為了配合客戶端聊天的需求,也稍微做了點改變。
<?php $requestparam = isset($_GET['callback'])?$_GET['callback']:'callback'; // 青云志聊天機器人接口: http://api.qingyunke.com/api.php?key=free&appid=0&msg=hello // 接收來自客戶端的請求內容 $talk = $_REQUEST['talk']; $result = file_get_contents("http://api.qingyunke.com/api.php?key=free&appid=0&msg=$talk"); // 拼接一些字符串 echo $requestparam . "($result)"; ?>
最后來查看一下跨域的效果吧。
以上是“ajax如何解決跨域問題”這篇文章的所有內容,感謝各位的閱讀!相信大家都有了一定的了解,希望分享的內容對大家有所幫助,如果還想學習更多知識,歡迎關注億速云行業資訊頻道!
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。