您好,登錄后才能下訂單哦!
今天小編給大家分享的是ajax跨域的解決方案,相信很多人都不太了解,為了讓大家更加了解ajax跨域的解決方案,所以給大家總結(jié)了以下內(nèi)容,一起往下看吧。一定會(huì)有所收獲的哦。
1. AJAX
AJAX(Asynchronous JavaScript and XML),意思就是用JavaScript執(zhí)行異步網(wǎng)絡(luò)請(qǐng)求。
主要可以通過(guò)架設(shè)代理服務(wù)器,JSONP和CORS三種方案實(shí)現(xiàn)跨域
用JavaScript寫一個(gè)完整的AJAX代碼并不復(fù)雜,但是需要注意:AJAX請(qǐng)求是異步執(zhí)行的,也就是說(shuō),要通過(guò)回調(diào)函數(shù)獲得響應(yīng)。
創(chuàng)建ajax的過(guò)程一般如下:
創(chuàng)建XMLHttpRequest對(duì)象,也就是創(chuàng)建一個(gè)異步調(diào)用對(duì)象;判斷XHR對(duì)象屬性;創(chuàng)建一個(gè)新的HTTP請(qǐng)求,并指定該HTTP請(qǐng)求的方法、URL及驗(yàn)證信息;設(shè)置響應(yīng)HTTP請(qǐng)求狀態(tài)變化的函數(shù);發(fā)送HTTP請(qǐng)求;獲取異步調(diào)用返回的數(shù)據(jù);使用JavaScript和DOM實(shí)現(xiàn)局部刷新。
代碼。
var xmlhttp;function createXMLHttpRequest () { xmlhttp = null; if (window.XMLHttpRequest) { xmlhttp = new XMLHttpRequest(); } else if (window.ActiveXObject) { xmlhttp = new ActiveXObject('Microsoft.XMLHTTP'); } // 異步調(diào)用服務(wù)器段數(shù)據(jù) if (xmlhttp != null) { // 創(chuàng)建http請(qǐng)求 xmlhttp.open('GET/POST', url, true); // 設(shè)置http請(qǐng)求狀態(tài)變化的函數(shù) xmlhttp.onreadystatechange = httpStateChange; // 發(fā)送請(qǐng)求 xmlhttp.send(null); } else { console.log('不支持XHR'); } } // 響應(yīng)HTTP請(qǐng)求狀態(tài)變化的函數(shù)function httpStateChange () { //判斷異步調(diào)用是否完成 if (xmlhttp.readyState == 4) {//readyState==4表示后臺(tái)處理完成了 if (xmlhttp.status >= 200 && xmlhttp.status < 300 || xmlhttp.status == 304){ //判斷異步調(diào)用是否成功,如果成功開始局部更新數(shù)據(jù) //code... } else{ console.log("出錯(cuò)狀態(tài)碼:" + xmlhttp.status + "出錯(cuò)信息:" + xmlhttp.statusText); } } }
對(duì)于低版本的IE,需要換一個(gè)ActiveXObject對(duì)象,如果你想把標(biāo)準(zhǔn)寫法和IE寫法混在一起,可以這么寫。
var request;if (window.XMLHttpRequest) { request = new XMLHttpRequest(); } else { request = new ActiveXObject('Microsoft.XMLHTTP'); }
通過(guò)檢測(cè)window對(duì)象是否有XMLHttpRequest屬性來(lái)確定瀏覽器是否支持標(biāo)準(zhǔn)的XMLHttpRequest。注意,不要根據(jù)瀏覽器的navigator.userAgent來(lái)檢測(cè)瀏覽器是否支持某個(gè)JavaScript特性,一是因?yàn)檫@個(gè)字符串本身可以偽造,二是通過(guò)IE版本判斷JavaScript特性將非常復(fù)雜。
當(dāng)創(chuàng)建了XMLHttpRequest對(duì)象后,要先設(shè)置onreadystatechange
的回調(diào)函數(shù)。在回調(diào)函數(shù)中,通常我們只需通過(guò)readyState === 4判斷請(qǐng)求是否完成,如果已完成,再根據(jù)status判斷是否是一個(gè)成功的響應(yīng)。
XMLHttpRequest對(duì)象的open()方法有3個(gè)參數(shù),第一個(gè)參數(shù)指定是GET還是POST,第二個(gè)參數(shù)指定URL地址,第三個(gè)參數(shù)指定是否使用異步,默認(rèn)是true,所以不用寫。注意,千萬(wàn)不要把第三個(gè)參數(shù)指定為false,否則瀏覽器將停止響應(yīng),直到AJAX請(qǐng)求完成。如果這個(gè)請(qǐng)求耗時(shí)10秒,那么10秒內(nèi)你會(huì)發(fā)現(xiàn)瀏覽器處于“假死”狀態(tài)。
最后調(diào)用send()方法才真正發(fā)送請(qǐng)求。GET請(qǐng)求不需要參數(shù),POST請(qǐng)求需要把body部分以字符串或者FormData對(duì)象傳進(jìn)去。
2. 跨域安全限制
因?yàn)闉g覽器的“同源策略”,協(xié)議、域名、端口號(hào)若有一個(gè)不同,則不能訪問。AJAX本身是不能跨域的,AJAX直接請(qǐng)求普通文件存在跨域無(wú)權(quán)限訪問的問題,只要是跨域請(qǐng)求,一律不準(zhǔn);但是配合后臺(tái)可以跨域。
因?yàn)橥床呗韵拗频氖菫g覽器但是對(duì)服務(wù)器不限制,服務(wù)器可以跨域。
那是不是用JavaScript無(wú)法請(qǐng)求外域(就是其他網(wǎng)站)的URL了呢?方法還是有的,大概有以下幾種。
2.1 CORS
CORS(Cross-Origin Resource Sharing,跨源資源共享)是W3C的一個(gè)草案,定義了在必須訪問跨域資源時(shí),瀏覽器與服務(wù)器應(yīng)該如何溝通。
CORS背后的基本思想就是使用自定義的HTTP頭部讓瀏覽器與服務(wù)器進(jìn)行溝通,從而決定請(qǐng)求或響應(yīng)是應(yīng)該成功,還是應(yīng)該失敗。
比如一個(gè)簡(jiǎn)單的使用GET或者POST發(fā)送的請(qǐng)求,它沒有自定義頭部,而主體內(nèi)容是text/plain。在發(fā)送該請(qǐng)求時(shí),需要給它附加一個(gè)額外的Origin頭部,其中包含請(qǐng)求頁(yè)面的源信息(協(xié)議、域名和端口),以便服務(wù)器根據(jù)這個(gè)頭部信息來(lái)決定是否給予響應(yīng)。下面是Origin頭部的一個(gè)示例。
Origin: http://www.nczonline.net
如果服務(wù)器認(rèn)為這個(gè)請(qǐng)求可以接受,就在Access-Control-Allow-Origin頭部中回發(fā)相同的源信息(如果是公共資源,可以回發(fā)'*')。例如:
Access-Control-Allow-Origin: http://www.nczonline.net
如果沒有這個(gè)頭部,或者有這個(gè)頭部但源信息不匹配,瀏覽器就會(huì)駁回請(qǐng)求。正常情況下,瀏覽器會(huì)處理請(qǐng)求。注意,請(qǐng)求進(jìn)而響應(yīng)都不包含cookie信息。
目前,所有瀏覽器都支持該功能,IE瀏覽器不能低于IE10。整個(gè)CORS通信過(guò)程,都是瀏覽器自動(dòng)完成,不需要用戶參與。對(duì)于開發(fā)者來(lái)說(shuō),CORS通信與同源的AJAX通信沒有差別,代碼完全一樣。瀏覽器一旦發(fā)現(xiàn)AJAX請(qǐng)求跨源,就會(huì)自動(dòng)添加一些附加的頭信息,有時(shí)還會(huì)多出一次附加的請(qǐng)求,但用戶不會(huì)有感覺。
因此,實(shí)現(xiàn)CORS通信的關(guān)鍵是服務(wù)器。只要服務(wù)器實(shí)現(xiàn)了CORS接口,就可以跨源通信。
平時(shí)的ajax請(qǐng)求可能是這樣的:
<script type="text/javascript"> var xhr = new XMLHttpRequest(); xhr.open("POST", "/damonare",true); xhr.send();</script>
以上damonare部分是相對(duì)路徑,如果我們要使用CORS,相關(guān)Ajax代碼可能如下所示:
<script type="text/javascript"> var xhr = new XMLHttpRequest(); xhr.open("GET", "http://segmentfault.com/u/trigkit4/",true); xhr.send();</script>
代碼與之前的區(qū)別就在于相對(duì)路徑換成了其他域的絕對(duì)路徑,也就是你要跨域訪問的接口地址。
服務(wù)器端對(duì)于CORS的支持,主要就是通過(guò)設(shè)置Access-Control-Allow-Origin來(lái)進(jìn)行的。如果瀏覽器檢測(cè)到相應(yīng)的設(shè)置,就可以允許Ajax進(jìn)行跨域的訪問。
2.2 圖像Ping
我們知道,一個(gè)網(wǎng)頁(yè)可以從任何網(wǎng)頁(yè)中加載圖像,不用擔(dān)心跨域不跨域。這也是在線廣告跟蹤瀏覽量的主要方式。我們也可以動(dòng)態(tài)的創(chuàng)建圖像,使用它們的onload和onerror事件處理成西來(lái)確定是否接收到了響應(yīng)。
動(dòng)態(tài)創(chuàng)建圖像經(jīng)常用于圖像Ping。
圖像Ping是與服務(wù)器進(jìn)行簡(jiǎn)單、單向的跨域通信的一種方式。請(qǐng)求的數(shù)據(jù)是通過(guò)查詢字符串形式發(fā)送的,而響應(yīng)可以是任意內(nèi)容,但通常是像素圖或204響應(yīng)。通過(guò)圖像Ping,瀏覽器得不到任何具體的數(shù)據(jù),但通過(guò)偵聽load和error事件,它能知道響應(yīng)是什么時(shí)候收到的。
來(lái)看下面的例子。
var img = new Image(); img.onload = img.onerror = function () { console.log('Done'); }; img.src = 'http://www.example.com/test?name=Nico';
這里創(chuàng)建了一個(gè)Image的實(shí)例,然后將onload和onerror事件處理程序指定為同一個(gè)函數(shù)。這樣無(wú)論是什么響應(yīng),只要請(qǐng)求完成,就能得到通知。請(qǐng)求從設(shè)置src屬性那一刻開始,而這個(gè)例子在請(qǐng)求中發(fā)送了一個(gè)name參數(shù)。
圖像Ping最常用于跟蹤用戶點(diǎn)擊頁(yè)面或動(dòng)態(tài)廣告曝光次數(shù)。
圖像Ping有兩個(gè)主要的缺點(diǎn):
只能發(fā)送GET請(qǐng)求。無(wú)法訪問服務(wù)器的響應(yīng)文本。
因此,圖像Ping只能用于瀏覽器與服務(wù)器間的單向通信。
2.3 JSONP
JSONP是JSON with padding(填充式JSON或參數(shù)式JSON)的簡(jiǎn)寫,是應(yīng)用JSON的一種新方法。JSONP與JSON看起來(lái)差不多,只不過(guò)是被包含在函數(shù)調(diào)用中的JSON,如下。
callback({'name': 'Azure'});
JSONP由兩部分組成:回調(diào)函數(shù)和數(shù)據(jù)?;卣{(diào)函數(shù)是當(dāng)響應(yīng)到來(lái)時(shí)應(yīng)該在頁(yè)面中調(diào)用的函數(shù)?;卣{(diào)函數(shù)的名字一般是在請(qǐng)求中指定的,而數(shù)據(jù)就是傳入回調(diào)參數(shù)中JSON數(shù)據(jù)。下面是一個(gè)典型的JSONP請(qǐng)求。
http://freegeoip.net/json/?callback=handleResponse
這個(gè)URL是在請(qǐng)求一個(gè)JSONP地理定位服務(wù)。通過(guò)查詢字符串來(lái)指定JSONP服務(wù)的回調(diào)參數(shù)是很常見的,就像上面的URL所示,這里指定的回調(diào)函數(shù)的名字叫handleResponse()。
JSONP是通過(guò)動(dòng)態(tài)<script>元素來(lái)使用的,使用時(shí)可以為src屬性指定一個(gè)跨域URL。
這里的<scriot>元素與<img>元素類似,都有能力不受限制的從其他域加載資源。因?yàn)镴SONP是有效的JS代碼,所以在請(qǐng)求完成后,即在JSONP響應(yīng)加載到頁(yè)面中以后,就會(huì)立即執(zhí)行。來(lái)看一個(gè)例子。
function handleResponse (response) { console.log('u r at IP address ' + response.ip + ', which is in ' + response.city + ', ' + response.region_name); } var script = document.createElement('script'); script.src = 'http://freegeoip.net/json/?callback=handleResponse'; document.body.insertBefore(script, document.body.firstChild);
這個(gè)例子通過(guò)查詢地理定位服務(wù)來(lái)顯示IP地址和地理位置信息。
JSONP之所以在開發(fā)人員中極為流行,主要原因是它非常簡(jiǎn)單易用。與圖像Ping相比,它的優(yōu)點(diǎn)在于能夠直接訪問響應(yīng)文本,支持在瀏覽器與服務(wù)器之間雙向通信。不過(guò),JSONP也有兩點(diǎn)不足。
首先,安全性問題。JSONP是從其他域中加載代碼執(zhí)行。如果其他域不安全,很可能會(huì)在響應(yīng)中夾帶一些惡意代碼,而此時(shí)除了完全放棄JSONP調(diào)用之外,沒有辦法追究。因此在使用不是自己運(yùn)維的Web服務(wù)時(shí),一定得保證它安全可靠。
其次,要確定JSONP請(qǐng)求是否失敗并不容易。
CORS和JSONP對(duì)比
JSONP只能實(shí)現(xiàn)GET請(qǐng)求,而CORS支持所有類型的HTTP請(qǐng)求。使用CORS,開發(fā)者可以使用普通的XMLHttpRequest發(fā)起請(qǐng)求和獲得數(shù)據(jù),比起JSONP有更好的錯(cuò)誤處理。SONP主要被老的瀏覽器支持,它們往往不支持CORS,而絕大多數(shù)現(xiàn)代瀏覽器都已經(jīng)支持了CORS。
以上就是ajax跨域的解決方案的詳細(xì)內(nèi)容了,看完之后是否有所收獲呢?如果想了解更多相關(guān)內(nèi)容,歡迎來(lái)億速云行業(yè)資訊。
免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點(diǎn)不代表本網(wǎng)站立場(chǎng),如果涉及侵權(quán)請(qǐng)聯(lián)系站長(zhǎng)郵箱:is@yisu.com進(jìn)行舉報(bào),并提供相關(guān)證據(jù),一經(jīng)查實(shí),將立刻刪除涉嫌侵權(quán)內(nèi)容。