我为我的 Android 设备编写了一些代码,用于通过 HTTPS 登录网站并从结果页面中解析一些数据。一个HttpGet
首先获取登录所需的一些信息,然后HttpPost
执行实际的登录过程。
下面的代码在 Eclipse 中的 Java 项目中运行良好,该项目在构建路径上具有以下 JAR 文件:httpcore-4.1-beta2.jar
, httpclient-4.1-alpha2.jar
, httpmime-4.1-alpha2.jar
, and commons-logging-1.1.1.jar
.
public static MyBean gatherData(String username, String password) {
MyBean myBean = new MyBean();
try {
HttpResponse response = doHttpGet(URL_PAGE_LOGIN, null, null);
System.out.println("Got login page");
String content = EntityUtils.toString(response.getEntity());
String token = ContentParser.getToken(content);
String cookie = getCookie(response);
System.out.println("Performing login");
System.out.println("token = "+token +" || cookie = "+cookie);
response = doLoginPost(username,password,cookie, token);
int respCode = response.getStatusLine().getStatusCode();
if (respCode != 302) {
System.out.println("ERROR: not a 302 redirect!: code is \""+ respCode+"\"");
if (respCode == 200) {
System.out.println(getHeaders(response));
System.out.println(EntityUtils.toString(response.getEntity()).substring(0, 500));
}
} else {
System.out.println("Logged in OK, loading account home");
// redirect handler and rest of parse removed
}
}catch (Exception e) {
System.out.println("ERROR in gatherdata: "+e.toString());
e.printStackTrace();
}
return myBean;
}
private static HttpResponse doHttpGet(String url, String cookie, String referrer) {
try {
HttpClient client = new DefaultHttpClient();
client.getParams().setParameter(CoreProtocolPNames.PROTOCOL_VERSION, HttpVersion.HTTP_1_1);
client.getParams().setParameter(CoreProtocolPNames.HTTP_CONTENT_CHARSET, "UTF-8");
HttpGet httpGet = new HttpGet(url);
httpGet.getParams().setParameter(CoreProtocolPNames.PROTOCOL_VERSION, HttpVersion.HTTP_1_1);
httpGet.setHeader(HEADER_USER_AGENT,HEADER_USER_AGENT_VALUE);
if (referrer != null && !referrer.equals("")) httpGet.setHeader(HEADER_REFERER,referrer);
if (cookie != null && !cookie.equals("")) httpGet.setHeader(HEADER_COOKIE,cookie);
return client.execute(httpGet);
} catch (Exception e) {
e.printStackTrace();
throw new ConnectException("Failed to read content from response");
}
}
private static HttpResponse doLoginPost(String username, String password, String cookie, String token) throws ClientProtocolException, IOException {
try {
HttpClient client = new DefaultHttpClient();
client.getParams().setParameter(CoreProtocolPNames.PROTOCOL_VERSION, HttpVersion.HTTP_1_1);
client.getParams().setParameter(CoreProtocolPNames.HTTP_CONTENT_CHARSET, "UTF-8");
HttpPost post = new HttpPost(URL_LOGIN_SUBMIT);
post.getParams().setParameter(CoreProtocolPNames.PROTOCOL_VERSION, HttpVersion.HTTP_1_1);
post.setHeader(HEADER_USER_AGENT,HEADER_USER_AGENT_VALUE);
post.setHeader(HEADER_REFERER, URL_PAGE_LOGIN);
post.setHeader(HEADER_COOKIE, cookie);
post.setHeader("Content-Type","application/x-www-form-urlencoded");
List<NameValuePair> formParams = new ArrayList<NameValuePair>();
formParams.add(new BasicNameValuePair("org.apache.struts.taglib.html.TOKEN", token));
formParams.add(new BasicNameValuePair("showLogin", "true"));
formParams.add(new BasicNameValuePair("upgrade", ""));
formParams.add(new BasicNameValuePair("username", username));
formParams.add(new BasicNameValuePair("password", password));
formParams.add(new BasicNameValuePair("submit", "Secure+Log+in"));
UrlEncodedFormEntity entity = new UrlEncodedFormEntity(formParams,HTTP.UTF_8);
post.setEntity(entity);
return client.execute(post);
} catch (Exception e) {
e.printStackTrace();
throw new ConnectException("ERROR in doLoginPost(): "+e.getMessage());
}
}
当登录成功时,服务器(不受我的控制)返回 302 重定向,如果失败则返回 200 并重新加载登录页面。当使用上述 JAR 文件运行时,我得到 302 重定向,但是,如果我在构建路径上使用 1.6 Android JAR 文件运行 Android 项目中完全相同的代码,我会从服务器得到 200 响应。在 2.2 设备上运行代码时,我得到相同的 200 响应。
我的 Android 应用程序具有互联网权限,并且 HttpGet 工作正常。我假设问题在于 HttpPost (或其他一些类)在 Android JAR 版本和较新的 Apache 版本之间存在某些显着的差异。
我尝试将 Apache 库添加到 Android 项目的构建路径中,但由于重复的类,我收到如下消息:INFO/dalvikvm(390): DexOpt: not resolving ambiguous class 'Lorg/apache/http/impl/client/DefaultHttpClient;'
在日志中。我也尝试过使用MultipartEntity
而不是UrlEncodedFormEntity
但我得到相同的 200 结果。
所以,我有几个问题:
- 我可以强制在 Android 下运行的代码优先使用较新的 Apache 库而不是 Android 版本吗?
- 如果没有,有谁知道如何更改我的代码以便它与 Android JAR 文件一起使用?
- 还有其他完全不同的方法在 Android 中执行 HttpPost 吗?
- 还有其他想法吗?
I've read https://stackoverflow.com/questions/2253061/secure-http-post-in-android a https://stackoverflow.com/questions/3663701/cant-do-a-http-post-to-a-web-service-from-my-android-app lot https://stackoverflow.com/questions/2935946/sending-images-using-http-post of https://stackoverflow.com/questions/3522140 posts https://stackoverflow.com/questions/874227 and code http://code.google.com/p/and-bookworm/source/browse/trunk/src/com/totsp/bookworm/data/HttpHelper.java,但我一无所获。