Blueimp 論壇首頁


列印 2024/4/16 下午 01:35:09

文章作者 jieh2008/7/11 上午 11:12:54
smile   使用 Apache HttpClient 通過 Form-Based 認證
來源

Form-Based 認證相對 HTTP Basic 認證而言過程較為複雜,需要開發者記錄下相關的 cookie 資訊和部分 header 欄位並多次向站點發出請求。它的大致原理如下:

假定我 們需要訪問的受保護資源為 www.sample.com/sampleApp/sample.rss。首先我們需要向此保護資源發出請求。而由 Form-Based 認證原理一節中可知,J2EE 伺服器會將此請求重定向至 login.jsp。如果仔細分析 login.jsp 我們能發現它僅僅是一個 HTML 表單,其中有兩個欄位 j_username 和 j_password 分別記錄用戶名和密碼,而提交的目標則是 j_security_check。通常情況下,J2EE 構架會在每個站點應用的根節點定義一個 j_security_check 的資源。而我們的站點的應用程式根(Application Root)為 sampleApp。因而,通過將用戶名,密碼以及相關 cookie 和 header 欄位以 POST 方式發送至 www.sample.com/sampleApp/j_security_check 即可通過站點認證。在通過站點認證後,伺服器端將給出一個新的重定向,通常它將指向了用戶最初試圖訪問的受保護資源(本例中也就是 www.sample.com/sampleApp/sample.rss)。我們只需要再次創建訪問物件向此資源發出請求即可獲得其內容。

HttpClient client = new HttpClient();
client.getState().setCookiePolicy(CookiePolicy.COMPATIBILITY);

// 1
GetMethod authget = new GetMethod("httpwww.sample.comsampleAppsample.rss");
try {
client.executeMethod(authget);
}
catch (HttpException httpe) {
httpe.printStackTrace();
}
catch (IOException ioe) {
ioe.printStackTrace();
}

// 2
NameValuePair[] data = new NameValuePair[2];
data[0] = new NameValuePair("j_username", username);
data[1] = new NameValuePair("j_password", password);

PostMethod authpost = new PostMethod("http://www.sample.com/sampleApp/j_security_check");
authpost.setRequestBody(data);

// 3
Header hCookie = authget.getRequestHeader("Cookie");
Header hHost = authget.getRequestHeader("Host");
Header hUserAgent = authget.getRequestHeader("User-Agent");
if (hCookie == null || hHost == null || hUserAgent == null) {
return null;
}

authpost.setRequestHeader(hCookie);
authpost.setRequestHeader(hHost);
authpost.setRequestHeader(hUserAgent);

authget.releaseConnection();

try {
client.executeMethod(authpost);

// 4
Header header = authpost.getResponseHeader("location");
if (header != null) {
String newuri = header.getValue();
GetMethod redirect = new GetMethod(newuri);

client.executeMethod(redirect);
// process the content from the response
redirect.releaseConnection();
}
} catch (HttpException httpe) {
httpe.printStackTrace();
return null;
} catch (IOException ioe) {
ioe.printStackTrace();
return null;
}
authpost.releaseConnection();


其中各個步驟解釋如下:
1. 使用 GET 方式請求 sample.rss。伺服器收到連接後將在回應中給出連接資訊,HttpClient 在接收到回應後會將其保存至 cookie 中。
2. 準備第二次對 j_security_check 的連接,將用戶名和密碼填入新的 POST 請求的正文。
3. 將 cookie 和部分 header 欄位拷貝至新請求的報頭中,並發送請求。
4. 從認證成功的回應中獲取重定向,並對重定向指向的資源發出請求,獲取並處理內容。
----------------------------------------
支持小惡魔
BTC : 19tn3RnCuwZVukXAwyhDWZD4uBgUZoGJPx
LTC : LTFa17pSvvoe3aU5jbmfcmEpo1xuGa9XeA
知識跟八卦一樣,越多人知道越有價值;知識最好的備份方法,散播!
藍色小惡魔(林永傑): 臉書