不知道同學們在做項目的過程中有沒有相同的經歷呢?在使用 ajax 的時候,需要對請求參數和響應數據進行過濾處理,比如你們覺得就讓請求參數和響應信息就這么赤裸裸的在互聯網里來回的穿梭,比如這樣:
要知道,在浩瀚的互聯網中,所有的信息都是不安全的,萬一有人偷窺我們怎么辦?!萬一被別人看見了我們的美體,偷窺到了我們的私處,然后以此威脅我們,豈不是太難堪了不是?這時,你或許會想給請求數據和響應數據加密,就相當于給我們的數據穿上了一層衣服。于是我們這樣:
是不是美美噠,對,穿上一層漂漂亮亮的衣服,就不怕別人偷窺我們的美體了,我們出門的時候要穿衣服,回家的時候也要脫衣服,也就是說ajax請求的參數需要加密,ajax響應的數據的要解密,如果說項目只有幾個ajax請求需要加密的話還OK,發請求之前把data處理一遍,success回調函數把responseText解密一遍就完了。可是倘若架構大一點,ajax請求多一點,每次請求響應都要單獨處理加密解密啟不是太冗余了,于是我便去翻閱jQuery ajax參考手冊,還真的有不小的收獲。
首先jQuery有一個 ajaxSetup 方法,該方法可以設置全局 ajax 初始化參數,也就是說在聲明了該方法之后的所有 ajax 請求都會默認使用該方法設置的初始值。
然后我們再翻閱 ajax 參數,突然,我眼前一亮!有一個叫做 beforeSend 的方法,我一看這名字就亮了!這個函數也就是在發送 ajax 請求之前的回調函數,于是我們先把它用起來:
$.ajaxSetup({ beforeSend: function() { console.log(arguments);//我們先來看看這里面有什么好玩的東西 } });
然后我們在隨便發一個 ajax 請求:
$.ajax({ url: 'SetupServlet', type: 'GET', data: { param1: 'test1', param2: 'test2', } });
在控制臺我們可以看見打印的參數列表有兩個對象,我們先來看看 W3C 里對 beforeSend 的解釋:
beforeSend(XHR) 類型:Function 發送請求前可修改 XMLHttpRequest 對象的函數,如添加自定義 HTTP 頭。 XMLHttpRequest 對象是唯一的參數。 這是一個 Ajax 事件。如果返回 false 可以取消本次 ajax 請求。實際上這里是不對的,因為XHR不是唯一的參數,XHR只是 arguments[0] ,我們還有一個 arguments[1],我們來看看這是什么東西:
以下是在 Firefox Developer Edition(Firefox 的開發者版本,最近發現的,絕得超好用) 中打印的東西:
看到這里我們大致明白了,我們這個對象大致就是 ajax 的參數對象,由于我們本次實驗的目的是給我們將要在互聯網中遨游的數據穿衣服,那么我們看看這個衣服該穿在哪呢?在這個對象的 url 我們可以看到,jQuery 的 ajax 操作已經我們之前傳進來的參數序列化并附加在了 url 后面,因為這是 GET 請求。那么 POST 請求長什么樣呢?我們再來試一下:
$.ajax({ url: 'SetupServlet', type: 'POST', data: { param1: 'test1', param2: 'test2', }, });
現在這個參數對象長這個樣子:
我們可以看到不同之處在于 POST 請求多了一個 data 屬性,并且 url 后面沒有參數序列化字符串,但是 data 屬性卻是序列化之后的參數字符串。至此我們已經可以在 beforeSend 函數中對請求前的參數進行修改了,GET 請求修改 url 后面的參數,POST 請求修改 data 中的值,具體效果在這里暫時不演示。
但是到這里我依舊不是很爽啊,因為無論是 GET 還是 POST 的,我得到的都是序列化之后的字符串,要修改參數的話得先反序列化,然后才能處理,于是我又在 ajax API 當中尋找,功夫不負有心人,我找到了一個叫做 processData 的東西,先來看看官方解釋:
processData 類型:Boolean 默認值: true。默認情況下,通過data選項傳遞進來的數據,如果是一個對象(技術上講只要不是字符串),都會處理轉化成一個查詢字符串,以配合默認內容類型 "application/x-www-form-urlencoded"。如果要發送 DOM 樹信息或其它不希望轉換的信息,請設置為 false。也就是說默認情況下 jQuery 會自動幫我們把參數序列化,那么我們現在把它設置為 false 看看會發生什么:
$.ajaxSetup({ beforeSend: function() { console.log(arguments); }, processData: false, });
這時請求中的參數會發生如下變化
GET:
POST:
這里我只截取部分截圖,我們看到我們傳進來的參數在 POST 請求就是原生的對象,終于得到我想要的東西了,此時此刻我心中大喜!必須得抽根煙祝祝性,額不對...是祝祝興。于是我們可以拿這個 data 盡情的蹂躪,隨意的鞭打,我要把這個 data 對象盡情的踐踏!額,不好意思有點激動。回到正題,我們要給 data 穿衣服才對嘛,怎么說著說著就要開始脫衣服了...好的,下面我們開始穿衣服,在這里我以 base64 舉例,我對請求的參數進行 base64 編碼:
$.ajaxSetup({ beforeSend: function() { console.log(arguments); var params = arguments[1].data; var data = ''; for (var key in params) { //這兩行代碼的意思是進行 base64 編碼 var dataUtf8 = CryptoJS.enc.Utf8.parse(params[key]); var dataBase64 = CryptoJS.enc.Base64.stringify(dataUtf8); data = data.concat('&' + key + '=' + dataBase64); }; arguments[1].data = data.substring(1, data.length);//將序列化后的參數重寫 }, processData: false, });
于是乎,我們的請求參數就穿上了一身漂漂亮亮的衣服遨游在互聯網的世界里了,因為 jquery 在 GET 方法中會自動把 data 附加在 url 后面,所以將 processData 設置為 false 之后 url 后面會出現 [object object] ,這是 javascript 對象 toString() 過后的結果,也就是說我們的這個方法并不很適合 GET 方法,所以想給數據穿衣服的同學們還是乖乖的使用 POST 方法吧。
講到這里,發送數據我們解決了,但是接受數據呢?如果接受的數據也是進行加密的話,我們還需要對數據進行解密(說到這里還是得脫衣服[捂臉]),我們繼續翻閱 API ,于是我又看到了一個叫做 dataFilter 的東西,老規矩,先看官方解釋:
dataFilter 類型:Function 給 Ajax 返回的原始數據的進行預處理的函數。提供 data 和 type 兩個參數:data 是 Ajax 返回的原始數據,type 是調用 jQuery.ajax 時提供的 dataType 參數。函數返回的值將由 jQuery 進一步處理。該函數很簡單,就兩個參數,arguments[0] 是 ajax 的原始響應數據,也就是 XHR.responseText ,arguments[1] 是 ajax 請求參數中的 dataType ,而這個函數返回的值也就是 success 回調函數中的 responseText,這下就非常好辦了,我們先來測試下:
前端代碼發送 ajax 請求,后臺響應一句 "hello" ,然后我們在 dataFilter 里返回一句 "world"
前端代碼:
$.ajaxSetup({ beforeSend: function() { console.log(arguments); var params = arguments[1].data; var data = ''; for (var key in params) { //這兩行代碼的意思是進行 base64 編碼 var dataUtf8 = CryptoJS.enc.Utf8.parse(params[key]); var dataBase64 = CryptoJS.enc.Base64.stringify(dataUtf8); data = data.concat('&' + key + '=' + dataBase64); }; arguments[1].data = data.substring(1, data.length);//將序列化后的參數重寫 }, processData: false, dataFilter: function() { console.log(arguments);//這是我的一個習慣,拿到一個函數之后,管他是什么東西,先看看里面有什么參數 return "world"; } }); $.ajax({ url: 'SetupServlet', type: 'POST', dataType: 'text', data: { param1: 'test1', param2: 'test2', }, success: function(responseText) { console.log(responseText); }, });
后臺代碼(java):
String param1 = request.getParameter("param1"); String param2 = request.getParameter("param2"); System.out.println("param1: " + param1); System.out.println("param2: " + param2); response.getWriter().write("hello");
后端輸出:
前端輸出:
看來一切正常,現在我們加密和解密的過程進行一條龍的處理:
前端:
$.ajaxSetup({ beforeSend: function () { var params = arguments[1].data; var data = ''; for (var key in params) { var dataUtf8 = CryptoJS.enc.Utf8.parse(params[key]); var dataBase64 = CryptoJS.enc.Base64.stringify(dataUtf8); data = data.concat('&' + key + '=' + dataBase64); }; arguments[1].data = data.substring(1, data.length); }, processData: false, dataFilter: function () { var result = ''; try { var a = CryptoJS.enc.Base64.parse(arguments[0]); var result = CryptoJS.enc.Utf8.stringify(a); } catch(e) { result = arguments[0]; } finally { return result; } } });
后臺:
String param1 = request.getParameter("param1"); String param2 = request.getParameter("param2"); byte[] buffer1 = Base64.decodeBase64(param1); byte[] buffer2 = Base64.decodeBase64(param2); System.out.println("param1: " + new String(buffer1)); System.out.println("param2: " + new String(buffer2)); response.getWriter().write(Base64.encodeBase64String("hello".getBytes()));
后臺輸出:
前端輸出:
至此已經大功告成了,讓我們來總結下我們使用過的東西
第一個: ajaxSetup 這是設置全局的初始屬性
然后是三個屬性:
beforeSend:發送前執行的函數
processData:默認不序列化參數
dataFilter:對響應的數據進行過濾
然后,我們就可以給我們的數據穿上一層漂漂亮亮的衣服了。
以上就是本文的全部內容,希望本文的內容對大家的學習或者工作能帶來一定的幫助,同時也希望多多支持綠夏網!