課題:
編寫一個Android應用,訪問一個基於Http服務的資料服務系統,為了提高安全性,該資料服務系統採用了Http Digest認證體系,理由是,相比基本認證方式而言,Digest認證可以保證認證資訊(使用者名稱和密碼)的傳輸安全,同時比SSL簡單易用。在使用瀏覽器訪問時,會提示一個使用者名稱和密碼對話方塊,但如果是程式訪問,就需要在程式訪問過程中編程提供認證資訊。
要求:
-- 在程式中可以設定使用者名稱和密碼
-- 可以通過網路訪問基於Digest認證和Http資料服務(JSON格式)
-- 使用Android基本庫,不使用其他擴充庫(基於相容性考慮)
-- 支援Android2.2以上系統
-- 技術實現簡單清晰
實現:
網路上提供的一些解決方案都有一些問題,如需要使用第三方的類庫,建立認證器,手工佈建要求參數等等,都比較麻煩,而且問題很多,經過摸索,我在程式中實現了基於Android標準庫的認證過程,實現思路、過程和範例程式碼如下:
基礎邏輯是:
--- 使用HttpClient(DefaultHttpClient)類串連伺服器並擷取資料
DefualtHttpClient 類:建立client對象
excuete(HttpGet)方法:執行串連和擷取,參數是一個HttpGet對象
HttpGet類:基於url建立HttpGet對象
HttpResponse類: execute的傳回值
getEntiry().getContent() 方法:擷取資料流
--- 該client訪問需要認證的資源需要一個認證方法,就需要設定一個認證提供者
client的 setCredentialsProvider(bcp) 方法:設定認證提供者
BasicCredentialsProvider 類:建立認證提供者執行個體
setCredentials 方法:設定AuthScope和UsernamePasswordCredentials類
AuthScope類:認證範圍,基於主機,連接埠和領域構建
UsernamePasswordCredentials:基於使用者名稱和口令的認證,基於使用者名稱和口令構建
實現代碼如下:
// 1. 擷取並設定url地址,一個字串變數,一個URL對象
String urlStr ="http://<host>:<port>/data.json";
URL url= new URL(urlStr);
// 2. 建立一個密碼認證,(UsernamePasswordCredentials類)
String username="foo";
String password="bar";
UsernamePasswordCredentials upc = new UsernamePasswordCredentials(username, password);
// 3. 設定認證範圍 (AuthScore類)
String strRealm = "<mydomain>";
String strHost = url.getHost();
int iPort = url.getPort();
AuthScope as = new AuthScope(strHost, iPort, strRealm);
// 4. 建立認證提供者(BasicCredentials類) ,基於as和upc
BasicCredentialsProvider bcp=new BasicCredentialsProvider();
bcp.setCredentials(as, upc);
// 5. 建立Http用戶端(DefaultHttpClient類)
DefaultHttpClient client=new DefaultHttpClient();
// 6. 為此用戶端設定認證提供者
client.setCredentialsProvider(bcp);
// 7. 建立一個get 方法(HttpGet類),基於所訪問的url地址
HttpGet hg= new HttpGet(urlStr);
// 8. 執行get方法並返回 response
HttpResponse hr = client.execute(hg);
// 9. 從response中取回資料,使用InputStreamReader讀取Response的Entity:
String line=null;
StringBuilder builder = new StringBuilder();
BufferedReader reader = new BufferedReader(new InputStreamReader(hr.getEntity().getContent() ));
while((line = reader.readLine()) != null) builder.append(line);
strContent=builder.toString();
總結
--- 對比Java中的實現,可以看到Andriod中的apache.http庫和commons-httpclient庫有比較大的結構和實現上的差異,這個原因導致了基於Java的實現不能直接移植到Android上。
--- 上述的實現簡單、邏輯清楚而容易理解,並且不涉及到更複雜的Digest認證的技術細節,而是由CredentialsProvider封裝了。
--- 上述實現沒有使用通常的connection類,而是client類,提供更豐富的串連和狀態控制功能,相比較而言,connection更加簡單
--- 使用者名稱和密碼作為認證架構中的參數而不是http request的組成部分,更加安全
--- 這裡沒有討論區伺服器端的實現,實際上我是通過Rails來實現http digest的。但理論上這種認證方式是標準。
✿果斷收藏的文章,本文並非原創,轉自:http://hi.baidu.com/yan__jh/blog/item/d6a689c17d33502ce4dd3b01.html
作者:yiyaaixuexi 發表於2011-7-18 20:28:27 原文連結 閱讀:144 評論:1 查看評論