2010-11-19 70 views
5

我已經爲我的Android設備編寫了一些代碼,通過https登錄到網站,並從結果頁面中解析出一些數據。一個HttpGet首先發生登錄需要一些信息,然後HttpPost做實際的登錄過程。 httpcore-4.1-beta2.jarhttpclient-4.1-alpha2.jarhttpmime-4.1-alpha2.jarcommons-logging-1.1.1.jar:下面HttpPost在Java項目中工作,而不在Android中

中的代碼在Eclipse中的Java項目,具有構建路徑上的下列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應用程序具有Internet權限,並且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?
- 有沒有其他想法?

我已經readalotofpostscode但我沒有在任何地方獲得。我一直堅持這一兩天,我不知道如何讓事情發揮作用,所以我會在這一點上嘗試任何事情。提前致謝。

回答

6

我現在已經放棄了獲得HttpClient路線,得到所需的響應從Android上運行時從服務器。相反,我重寫了上面的doPost方法,以代替使用HttpsURLConnection。這是新的(工作)版本,希望對某人有用。

private static LoginBean altPost(String username, String password, String cookie, String token){ 
    LoginBean loginBean = new LoginBean(); 
    HttpsURLConnection urlc = null; 
    OutputStreamWriter out = null; 
    DataOutputStream dataout = null; 
    BufferedReader in = null; 
    try { 
     URL url = new URL(URL_LOGIN_SUBMIT); 
     urlc = (HttpsURLConnection) url.openConnection(); 
     urlc.setRequestMethod("POST"); 
     urlc.setDoOutput(true); 
     urlc.setDoInput(true); 
     urlc.setUseCaches(false); 
     urlc.setAllowUserInteraction(false); 
     urlc.setRequestProperty(HEADER_USER_AGENT, HEADER_USER_AGENT_VALUE_FF); 
     urlc.setRequestProperty("Cookie", cookie); 
     urlc.setRequestProperty("Content-Type","application/x-www-form-urlencoded"); 
     String output = "org.apache.struts.taglib.html.TOKEN="+ URLEncoder.encode(token, HTTP.UTF_8) 
       +"&showLogin=true&upgrade=&username="+ URLEncoder.encode(username, HTTP.UTF_8) 
       +"&password="+ URLEncoder.encode(password, HTTP.UTF_8)+"&submit=" 
       +URLEncoder.encode("Secure+Log+in", HTTP.UTF_8); 
     dataout = new DataOutputStream(urlc.getOutputStream()); 
     // perform POST operation 
     dataout.writeBytes(output); 
     // get response info 
     loginBean.setResponseCode(urlc.getResponseCode()); 
     // get required headers 
     String headerName = null; 
     StringBuffer newCookie = new StringBuffer(100); 
     String redirectLocation = ""; 
     for (int i=1; (headerName = urlc.getHeaderField(i)) != null;i++) { 
      if (headerName.indexOf(COOKIE_VALUE_SESSION) > -1) { 
       if (newCookie.length() > 0) {newCookie.append("; ");} 
       newCookie.append(headerName); 
      } 
      if (headerName.indexOf(COOKIE_VALUE_AUTH) > -1) { 
       if (newCookie.length() > 0) {newCookie.append("; ");} 
       newCookie.append(headerName); 
      } 
      if (headerName.indexOf("https://") > -1) { 
       redirectLocation = headerName; 
      } 
     } 
     loginBean.setCookie(newCookie.toString()); 
     loginBean.setRedirectUrl(redirectLocation); 

     in = new BufferedReader(new InputStreamReader(urlc.getInputStream()),8096); 
     String response; 
     // write html to System.out for debug 
     while ((response = in.readLine()) != null) { 
      System.out.println(response); 
     } 
     in.close(); 
    } catch (ProtocolException e) { 
     e.printStackTrace(); 
    } catch (IOException e) { 
     e.printStackTrace(); 
    } finally { 
     if (out != null) { 
      try { 
       out.close(); 
      } catch (IOException e) { 
       e.printStackTrace(); 
      } 
     } 
     if (in != null) { 
      try { 
       in.close(); 
      } catch (IOException e) { 
       e.printStackTrace(); 
      } 
     } 
    } 
    return loginBean; 
} 

我仍然不知道爲什麼HttpClient方式無法正常工作。

+1

很好的答案。在薑餅和後來,HttpURLConnection是要走的路。不推薦使用Apache HttpClient。 – 2011-03-10 19:26:47

0

該網站是否有可能進行用戶代理檢測,並且實際返回不同的結果,因爲它是Android?鑑於200意味着成功,爲什麼它必須給302而不是200?你是否打印出返回200時得到的結果,並提供其他信息?

+0

的200結果僅僅是用戶登錄頁面再次,與沒有錯誤信息或其他信息,這是正確的登錄錯誤。我在頭文件中明確地設置了用戶代理,並且它被設置爲與代碼被調用的方式相同。我可以從我的android手機上的瀏覽器登錄到該網站,這意味着它不會基於它的android事實阻止。 – 2010-11-19 03:38:45

0

檢查RedirectHandler,覆蓋默認的一個,並做一些記錄在裏面,我有這樣的問題將Android的時候......

+0

我對重定向代碼(我沒有在上面提到過)很滿意,問題是我沒有那麼遠。由於服務器正在從Android返回200代碼而不是從Eclipse返回的302代碼,因此我沒有進入需要處理重定向的部分。 – 2010-11-19 12:54:08

+0

哼,這可能是一個用戶代理問題嗎? – dacwe 2010-11-20 16:53:02

+0

用戶代理在上面的代碼中設置,並且設置爲相同的值,無論它是在Android中運行還是作爲純Java運行。我試過了一個android用戶代理,一個FF/windows和一些自定義的代理。他們都給出了相同的行爲。 – 2010-11-23 00:07:52

1

避免碰撞用這個罐子的HttpClient

httplib

和這個職位也將是非常有用的

stack overflow post

+0

將有助於未來使用的人... – 2012-10-05 06:39:38

相關問題