田紹東 徐萬(wàn)明
摘要:Android是當(dāng)前主流移動(dòng)設(shè)備操作系統(tǒng)之一,基于Android系統(tǒng)的軟件也非常多,但Android系統(tǒng)上的軟件直接訪問(wèn)網(wǎng)絡(luò)數(shù)據(jù)庫(kù)有一定的風(fēng)險(xiǎn),該文對(duì)Android軟件訪問(wèn)網(wǎng)絡(luò)數(shù)據(jù)庫(kù)技術(shù)進(jìn)行研究,提出兩種更安全的Android訪問(wèn)網(wǎng)絡(luò)數(shù)據(jù)庫(kù)代理技術(shù)。
關(guān)鍵詞:Android;網(wǎng)絡(luò)數(shù)據(jù)庫(kù);遠(yuǎn)程訪問(wèn)
中圖分類號(hào):TP311 文獻(xiàn)標(biāo)識(shí)碼:A 文章編號(hào):1009-3044(2018)03-0014-02
目前基于Android系統(tǒng)的手機(jī)在市場(chǎng)占據(jù)較大的份額。據(jù)CodeForge網(wǎng)站發(fā)布2016年上半年《中國(guó)程序員調(diào)查報(bào)告》中顯示:在移動(dòng)端市場(chǎng),程序員們使用Android系統(tǒng)所占比例為79%,使用IOS系統(tǒng)的所占比例為18% 。Android系統(tǒng)下手機(jī)軟件大多數(shù)都要與網(wǎng)絡(luò)數(shù)據(jù)庫(kù)進(jìn)行交互,從而實(shí)現(xiàn)軟件相關(guān)功能。但是當(dāng)下基于Android環(huán)境下直接連接、訪問(wèn)網(wǎng)絡(luò)數(shù)據(jù)庫(kù)的技術(shù)并不安全。因此研究Android環(huán)境下如何安全地訪問(wèn)網(wǎng)絡(luò)數(shù)據(jù)庫(kù)的技術(shù)具有重要意義。
1 Android直接連接網(wǎng)絡(luò)數(shù)據(jù)的風(fēng)險(xiǎn)
相信許多Android程序員都知道在Android環(huán)境下連接數(shù)據(jù)的技術(shù),簡(jiǎn)單方式是使用JDBC(Java Database Connectivity,java數(shù)據(jù)庫(kù)連接)來(lái)連接數(shù)據(jù)庫(kù)。
JDBC是一種用于執(zhí)行SQL語(yǔ)句的Java API,可以為多種關(guān)系數(shù)據(jù)庫(kù)提供統(tǒng)一訪問(wèn),它由一組用Java語(yǔ)言編寫的類和接口組成。JDBC提供了一種基準(zhǔn),據(jù)此可以構(gòu)建更高級(jí)的工具和接口,使數(shù)據(jù)庫(kù)開(kāi)發(fā)人員能夠編寫數(shù)據(jù)庫(kù)應(yīng)用程序[1]。
我們來(lái)見(jiàn)識(shí)一下使用JDBC連接數(shù)據(jù)的關(guān)鍵部分的代碼,以連接SQL數(shù)據(jù)庫(kù)為例。
Connection conn = DriverManager.getConnection
("jdbc:microsoft:sqlserver://host:port; DatabaseName=database","user","pwd");
上述代碼是通過(guò)Connection接口連接SQL數(shù)據(jù)庫(kù),并在連接上傳送SQL指令,以實(shí)現(xiàn)相關(guān)數(shù)據(jù)庫(kù)操縱功能。分析getConnection方法中的參數(shù),容易知道這里包含了訪問(wèn)數(shù)據(jù)的類型,數(shù)據(jù)庫(kù)服務(wù)器的IP,端口號(hào),數(shù)據(jù)庫(kù)名,訪問(wèn)數(shù)據(jù)用戶名,訪問(wèn)數(shù)據(jù)用戶的密碼等信息。那么如果這些信息被別有用心的人知道了會(huì)有什么后果?這就是Android直接連接網(wǎng)絡(luò)數(shù)據(jù)的風(fēng)險(xiǎn)!它可能暴露數(shù)據(jù)庫(kù)訪問(wèn)的重要信息,可能帶來(lái)非常嚴(yán)重的后果。我們想想為什么支付寶、微信、電信翼支付等只給程序員編程的支付接口?而不是如上的訪問(wèn)數(shù)據(jù)庫(kù)的方式。
2 代理訪問(wèn)網(wǎng)絡(luò)數(shù)據(jù)技術(shù)
研究Android環(huán)境下訪問(wèn)網(wǎng)絡(luò)數(shù)據(jù)庫(kù)的人員很多,他們結(jié)合前人的智慧提出了一些較好的訪問(wèn)網(wǎng)絡(luò)數(shù)據(jù)庫(kù)的方法,如彭鳳凌提出了使用消息的模塊化交互結(jié)構(gòu)系統(tǒng)來(lái)實(shí)現(xiàn)Android手機(jī)與遠(yuǎn)程數(shù)據(jù)庫(kù)的交互[2];田佳影在文章中寫道使用Servlet進(jìn)行數(shù)據(jù)交互,結(jié)合HttpClient組建來(lái)傳送數(shù)據(jù),進(jìn)而實(shí)現(xiàn)Android訪問(wèn)遠(yuǎn)程數(shù)據(jù)庫(kù)[3]。龔成瑩在其論文中提到Android遠(yuǎn)程數(shù)據(jù)庫(kù)使用JSON格式交互信息的方便性[4]。徐萬(wàn)明等提出了通過(guò)WebService實(shí)現(xiàn)了Android系統(tǒng)訪問(wèn)SQLServer數(shù)據(jù)庫(kù)的例子[5]。
本人結(jié)合某Android項(xiàng)目研發(fā),提出兩種安全訪問(wèn)網(wǎng)絡(luò)數(shù)據(jù)庫(kù)的方法。
2.1 使用JSON數(shù)據(jù)格式與ASPX網(wǎng)頁(yè)交互操作訪問(wèn)數(shù)據(jù)庫(kù)
在某Android項(xiàng)目研發(fā)過(guò)程中,考慮到安全性不能使用JDBC與數(shù)據(jù)庫(kù)直接連接進(jìn)行數(shù)據(jù)操縱,在Android程序中通過(guò)httpClient對(duì)象與ASPX網(wǎng)頁(yè)進(jìn)行數(shù)據(jù)交互,實(shí)現(xiàn)網(wǎng)絡(luò)數(shù)據(jù)交換,實(shí)現(xiàn)通過(guò)ASPX網(wǎng)頁(yè)代理訪問(wèn)數(shù)據(jù)庫(kù)。本方法的產(chǎn)生是源于AJAX訪問(wèn)ASPX網(wǎng)頁(yè)的技術(shù)。
下面將用戶登錄驗(yàn)證模塊當(dāng)示例展示通過(guò)ASPX網(wǎng)頁(yè)代理訪問(wèn)數(shù)據(jù)庫(kù)的大致過(guò)程。Android端軟件設(shè)計(jì)主要過(guò)程如下:
第一步:建立httpClient;
HttpClienthttpClient = new DefaultHttpClient();
第二步:生成使用POST方法的請(qǐng)求對(duì)象;
String url = "http://ServerHost:Port/ReplyAjaxGetData.aspx";
HttpPosthttpPost = new HttpPost(url);
第三步:建立請(qǐng)求參數(shù),并將之添加到HTTP請(qǐng)求體的對(duì)象;
HttpEntityrequestEntity = new UrlEncodedFormEntity(pairs);
httpPost.setEntity(requestEntity);
第四步:執(zhí)行請(qǐng)求對(duì)象,獲取服務(wù)器返回的相應(yīng)對(duì)象;
HttpResponse response = httpClient.execute(httpPost);
第五步:檢查相應(yīng)的狀態(tài)是否正常,狀態(tài)碼的值是200表示正常;
if (response.getStatusLine().getStatusCode() == 200) {
第六步:從相應(yīng)對(duì)象當(dāng)中取出數(shù)據(jù),放到entity當(dāng)中;
HttpEntity entity = response.getEntity();
BufferedReaderreader = new BufferedReader(new InputStreamReader(entity.getContent()));
第七步:解析返回JSON數(shù)據(jù),并判斷返回?cái)?shù)據(jù)。
if(res0.equals("LoginOK"))
{//登錄成功
……}
else {//登錄失敗
……}}
ASPX網(wǎng)頁(yè)不用寫界面,只要在頁(yè)面的Page_Load事件中處理發(fā)送過(guò)來(lái)的請(qǐng)求即可。主要過(guò)程如下:
第一步:取得HTTP請(qǐng)求的參數(shù);
stringcmdAction = Request["Action"];
第二步:判斷請(qǐng)求參數(shù)的值,可要據(jù)不同值做不同響應(yīng);
switch (cmdAction)
{ case“checklogin”:
//進(jìn)一步讀取更詳細(xì)的請(qǐng)求參數(shù)
param1 = Request.Params["Table"];
param2 = Request.Params["id"];
//查詢數(shù)據(jù)庫(kù)……返回結(jié)果
result=……;
break;
case “”:……;break;}
第三步:將結(jié)果輸出到Android端。
Response.Write(result);
Response.End();
這種使用ASPX網(wǎng)頁(yè)代理訪問(wèn)數(shù)據(jù)的方法相較其他方法而言比較簡(jiǎn)單,也比較安全,將數(shù)據(jù)庫(kù)相關(guān)重要的信息隱藏在了Web服務(wù)器上,安全性由Web服務(wù)器的安全來(lái)決定,相比Android直接訪問(wèn)數(shù)據(jù)要安全得多,在Android也只要提供訪問(wèn)ASPX網(wǎng)頁(yè)的URL及相關(guān)請(qǐng)求參數(shù),如果要對(duì)數(shù)據(jù)進(jìn)行操縱,最好再加上驗(yàn)證是否是合法用戶之后才能充許更新數(shù)據(jù)。
2.2 使用服務(wù)器端的中間層代理軟件訪問(wèn)網(wǎng)絡(luò)數(shù)據(jù)庫(kù)
服務(wù)器端的中間層代理軟件(Agent Access Database Software,簡(jiǎn)稱AADBS),是在某Android項(xiàng)目中開(kāi)發(fā)的專為代理訪問(wèn)數(shù)據(jù)庫(kù)的程序,它支持代理多個(gè)App軟件訪問(wèn)自己專屬的數(shù)據(jù)庫(kù),將多個(gè)不同的App軟件的數(shù)據(jù)放在AADBS的后方。它不僅支持Android訪問(wèn)遠(yuǎn)程網(wǎng)絡(luò)數(shù)據(jù)庫(kù),其他嵌入式系統(tǒng)也可以。
AADBS的主要工作原理是接收移動(dòng)端程序發(fā)送來(lái)的數(shù)據(jù)訪問(wèn)請(qǐng)求,并找到相應(yīng)數(shù)據(jù)庫(kù)進(jìn)行代理訪問(wèn),將訪問(wèn)結(jié)果返回給移動(dòng)端程序,大體結(jié)構(gòu)如圖1所示。
具體過(guò)程是:1) 由守護(hù)線程等待移動(dòng)端程序發(fā)送過(guò)來(lái)的數(shù)據(jù)訪問(wèn)連接,第一次連接的時(shí)候移動(dòng)端程序發(fā)送三個(gè)參數(shù),用戶名,密碼,移動(dòng)程序名,移動(dòng)程序名經(jīng)查詢轉(zhuǎn)換為要訪問(wèn)的數(shù)據(jù)庫(kù)名(在AADBS服務(wù)器上內(nèi)置有數(shù)據(jù)庫(kù),存儲(chǔ)移動(dòng)程序名,數(shù)據(jù)庫(kù)IP地址,端口號(hào),數(shù)據(jù)庫(kù)名,數(shù)據(jù)庫(kù)訪問(wèn)用戶名,數(shù)據(jù)庫(kù)訪問(wèn)密碼等信息)。經(jīng)驗(yàn)證用戶名與密碼成功后建立SESSION會(huì)話對(duì)象,進(jìn)行數(shù)據(jù)訪問(wèn)。2) 移動(dòng)程序發(fā)送過(guò)來(lái)的數(shù)據(jù)流中傳送SQL指令被打包為一個(gè)消息放到傳入消息隊(duì)列,由消息處理線程從消息隊(duì)列中提取消息,傳送至對(duì)應(yīng)的數(shù)據(jù)庫(kù)執(zhí)行SQL指令。3) 將SQL執(zhí)行結(jié)果打包放到傳出消息隊(duì)列。由消息發(fā)送線程通過(guò)之前建立的數(shù)據(jù)流將查詢結(jié)果返回給移動(dòng)程序端。AADBS內(nèi)部結(jié)構(gòu)如圖2所示。
AADBS是用C#程序設(shè)計(jì)語(yǔ)言基于.net平臺(tái)開(kāi)發(fā)的,具有很多優(yōu)點(diǎn):1)采用流行的面向?qū)ο蠹夹g(shù)將各對(duì)象進(jìn)行封裝,使用軟件具有較好的軟件結(jié)構(gòu)及較好的擴(kuò)展性。2)將各消息處理模塊封裝成線程,大大提升軟件并發(fā)執(zhí)行效率,使代理訪問(wèn)數(shù)據(jù)庫(kù)服務(wù)能同時(shí)處理多個(gè)連接訪問(wèn)請(qǐng)求,并且不因某個(gè)連接阻塞而影響其他的數(shù)據(jù)訪問(wèn)連接。3)在服務(wù)器上可支持多種數(shù)據(jù)庫(kù)驅(qū)動(dòng)程序,不受移動(dòng)端系統(tǒng)環(huán)境的限制,可訪問(wèn)多種類型的數(shù)據(jù)庫(kù)。4)在AADBS中加入日志記錄功能,記錄訪問(wèn)者IP、執(zhí)行的SQL指令等信息,可以實(shí)現(xiàn)數(shù)據(jù)訪問(wèn)的追溯以及方便數(shù)據(jù)恢復(fù)等。
最后,在移動(dòng)端程序中編寫類似于C#中的DataTable(數(shù)據(jù)表)類,DataRow(數(shù)據(jù)行)類等的類包,以及從數(shù)據(jù)流中提出數(shù)據(jù)的方法等。
3 結(jié)論
經(jīng)實(shí)際使用環(huán)境的檢驗(yàn),App上線運(yùn)行以來(lái),以上兩種方法代理移動(dòng)程序訪問(wèn)網(wǎng)絡(luò)數(shù)據(jù)庫(kù)的響應(yīng)速度令人滿意。重要的是數(shù)據(jù)庫(kù)的安全性得到了很好的解決,將數(shù)據(jù)庫(kù)訪問(wèn)的信息成功地隱藏在了服務(wù)器上,當(dāng)然這要做好服務(wù)器安全防護(hù)。使用服務(wù)器端的中間層代理軟件(AADBS)訪問(wèn)數(shù)據(jù)庫(kù)的方式不僅將數(shù)據(jù)庫(kù)隱藏在了服務(wù)器的后方,還支持代理多個(gè)App的網(wǎng)絡(luò)數(shù)據(jù)庫(kù)訪問(wèn)功能(只需在AADBS的數(shù)據(jù)庫(kù)中增加一行記錄)。
參考文獻(xiàn):
[1] 彭鳳凌.安卓手機(jī)與數(shù)據(jù)庫(kù)交互系統(tǒng)的設(shè)計(jì)與實(shí)現(xiàn)[J].計(jì)算機(jī)工程與設(shè)計(jì),2013,34(11):3907-3911.
[2] 田佳影.基于HttpClient的Android遠(yuǎn)程數(shù)據(jù)庫(kù)訪問(wèn)[J].電子世界.
[3] 龔成瑩,等.基于JSON的Android移動(dòng)終端與PHP及MySQL數(shù)據(jù)通信[J].工業(yè)儀表與自動(dòng)化裝置,2013(1):63-65.