2010-11-19 2 views
5

Я написал код для моего устройства Android для входа на веб-сайт за https и проанализировал некоторые данные из полученных страниц. HttpGet происходит сначала, чтобы получить необходимую информацию для входа в систему, а затем HttpPost, чтобы выполнить фактический процесс входа в систему.HttpPost работает в Java-проекте, а не в Android

ниже код отлично работает в проекте Java в Eclipse, который имеет следующие Jar файлы на пути сборки: httpcore-4.1-beta2.jar, httpclient-4.1-alpha2.jar, httpmime-4.1-alpha2.jar, 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, однако, если я запустил тот же самый код из проекта Android с 1,6 Android Jar-файлом на пути сборки, я получаю ответ 200 с сервера. Я получаю тот же ответ 200 при запуске кода на моем устройстве 2.2.

У моего приложения андроида есть разрешения в Интернете, и 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?
- Есть ли другие, совершенно разные подходы к выполнению HttpPost в Android?
- Любые другие идеи?

Я readalotofposts и code, но я не получаю нигде. Я застрял на этом пару дней, и я в недоумении, как заставить дело работать, поэтому я попробую что-нибудь в этот момент. Заранее спасибо.

ответ

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

хороший ответ. в Gingerbread, а позже, HttpURLConnection - это путь. рассмотрите устаревший Apache HttpClient. –

0

Возможно ли, что этот сайт обнаруживает пользовательский агент и фактически возвращает разные результаты, потому что это Android? Учитывая, что 200 подразумевает успех, почему он должен давать 302 вместо 200? Вы распечатали результат, который получаете, когда он возвращает 200, и дает ли он дополнительную информацию?

+0

200 результата только страница пользователя Войти снова, с нет сообщений об ошибках или другой информации, что обычно происходит с неправильным входом в систему. Я устанавливаю user-agent явно в заголовках, и он устанавливается таким же образом, как вызывается код. Я могу войти на сайт ОК из браузера на моем телефоне Android, что подразумевает, что он не блокирует, основываясь на его андроиде. –

0

Проверьте RedirectHandler, переопределить значение по умолчанию один и сделать некоторые протоколирование в нем, у меня были проблемы с этим при переходе на Android ...

+0

Я довольно доволен кодом перенаправления (который я не упоминал выше), проблема в том, что я даже не добираюсь так далеко. Поскольку сервер возвращает 200-й код от Android, а не 302, возвращенный из Eclipse, я не попаду в ту часть, где мне нужно обработать перенаправление. –

+0

Худ, может быть проблема с пользовательским агентом? – dacwe

+0

Пользовательский агент установлен в вышеуказанном коде и имеет то же значение, независимо от того, запущен ли он на Android или как чистая Java. Я пробовал пользовательский агент Android, FF/windows один и некоторые пользовательские. Все они дают такое же поведение. –

1

, чтобы избежать столкновения использовать эту баночку для HTTPClient

httplib

и этот пост также будет очень полезно

stack overflow post

+0

поможет кому-то для будущего использования ... –

Смежные вопросы