HTTP BASIC認證,搶先認證介紹和 HttpClient 4.1.1 例項
1.HTTP BASIC認證
在HTTP中,基本認證是一種用來允許Web瀏覽器或其他客戶端程式在請求時提供以使用者名稱和口令形式的憑證。在傳送之前,使用者名稱追加一個冒號然後串接上口令。得出的結果字串再用Base64演算法編碼。例如,使用者名稱是Aladdin,口令是open sesame,拼接後的結果是Aladdin:open sesame,然後再用Base64編碼,得到QWxhZGRpbjpvcGVuIHNlc2FtZQ==。Base64編碼的字串傳送出去,並由接收者解碼,得到一個由冒號分隔的使用者名稱和口令的字串。
在你訪問一個需要HTTP Basic Authentication的URL的時候,如果你沒有提供使用者名稱和密碼,伺服器就會返回401,如果你直接在瀏覽器中開啟,瀏覽器會提示你輸入使用者名稱 和密碼。你可以嘗試點選這個url看看效果:。使用者輸入使用者名稱稱和密碼,瀏覽器傳送帶認證的請求包。 HTTP伺服器在每次收到請求包後,根據協議取得客戶端附加的使用者資訊(BASE64加密的使用者名稱和密碼),解開請求包,對使用者名稱及密碼進行驗證,如果使用者名稱及密碼正確,則根據客戶端請求,返回客戶端所需要的資料;否則,返回錯誤程式碼或重新要求客戶端提供使用者名稱及密碼。
1.1認證流程
GET /statuses/friends_timeline.xml HTTP/1.1 Host: api.minicloud.com.cn User-Agent: Mozilla/5.0 (Windows NT 5.1; rv:2.0.1) Gecko/20100101 Firefox/4.0.1 Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8 Accept-Language: zh-cn,zh;q=0.5 Accept-Encoding: gzip, deflate Accept-Charset: GB2312,utf-8;q=0.7,*;q=0.7 Keep-Alive: 115 Connection: keep-alive
2.伺服器收到請求,發現使用者未登入,響應如下。
HTTP/1.1 401 Unauthorized Server: nginxDate: Wed, 08 Jun 2011 06:25:47 GMT Content-Type: application/xml; charset=UTF-8 Transfer-Encoding: chunked Connection: keep-alive WWW-Authenticate: Basic Vary: Accept-Charset, Accept-Encoding, Accept-Language, Accept Accept-Ranges: bytes
3,當符合http1.0或1.1規範的客戶端(如IE,FIREFOX)收到401返回值時,將自動彈出一個登入視窗,要求使用者輸入使用者名稱和密碼。
4,使用者輸入使用者名稱和密碼後,將使用者名稱及密碼以BASE64加密方式加密,並將密文放入前一條請求資訊中,則客戶端傳送的第一條請求資訊則變成如下內容:
GET /statuses/friends_timeline.xml HTTP/1.1
Host: api.minicloud.com.cn
.......
Connection: Keep-Alive
Authorization: Basic d2pqOjEyMzQ1Ng==
注:Basic之後表示加密後的使用者名稱及密碼。
5,伺服器收到上述請求資訊後,將Authorization欄位後的使用者資訊取出、解密,將解密後的使用者名稱及密碼與使用者資料庫進行比較驗證,如使用者名稱及密碼正確,伺服器則根據請求,將所請求資源傳送給客戶端:
HTTP/1.0 200 OK
Content-Type: text/html
Content-Length: xxxx
<html>
網頁內容
</html>
如使用者名稱及密碼不正確,請返回第2步,重新向客戶端傳送使用者驗證請求。
6,在以後的整個通訊會話中,客戶端均會在請求包中附加入加密後的使用者資訊。
2.搶先認證
搶先認證就是直接從上面第4步開始,在請求頭裡面加入使用者名稱稱和密碼資訊。直接向伺服器請求資訊。少了前面三步的操作。
3.HttpClient的實現
HttpClient does not support preemptive authentication out of the box, 因為如果搶先認證誤用或者使用不當會引起嚴重的質量問題,例如明文傳送使用者的憑證給未經授權的第三方。因此,使用者應該在他們特定應用環境裡面權衡使用搶先認證的潛在優勢和安全風險的矛盾。
儘管如此,我們仍然可以通過預先組裝認證資料快取來配置HttpClient 的搶先認證方式。
HttpHost targetHost = new HttpHost("api.t.sohu.com", 80, "http");
DefaultHttpClient httpclient = new DefaultHttpClient();
httpclient.getCredentialsProvider().setCredentials(
new AuthScope(targetHost.getHostName(), targetHost.getPort()),
new UsernamePasswordCredentials("username", "password"));
// Create AuthCache instance
AuthCache authCache = new BasicAuthCache();
// Generate BASIC scheme object and add it to the local auth cache
BasicScheme basicAuth = new BasicScheme();
authCache.put(targetHost, basicAuth);
// Add AuthCache to the execution context
BasicHttpContext localcontext = new BasicHttpContext();
localcontext.setAttribute(ClientContext.AUTH_CACHE, authCache);
String url ="http://api.t.sohu.com/statuses/update.xml";
HttpPost httpPost = new HttpPost(url);
httpPost.setHeader("Content-Type", "application/x-www-form-urlencoded");
for (int i = 0; i < 3; i++) {
HttpResponse response = httpclient.execute(targetHost, httpPost, localcontext);
HttpEntity entity = response.getEntity();
EntityUtils.consume(entity);
}