2010-08-08 17 views
10

Przeszedłem przez różne tutoriale i tę stronę, ale nie mogłem znaleźć odpowiedniego rozwiązania. Z drugiej strony widziałem aplikacje logujące się na stronach internetowych i żądające dalszych informacji, więc jestem pewien, że istnieje sposób, aby to zadziałało, ale może moje podejście jest złe.Android: zaloguj się na stronie internetowej i zachowaj sesję/cookie za pomocą DefaultHttpClient

Oto, co próbuję zrobić: chcę zalogować się do witryny, która wymaga uwierzytelnienia użytkownika, a następnie czytać i analizować witryny, które są dostępne tylko po zalogowaniu użytkownika. Problem: po wpisaniu poświadczeń do na stronie, otrzymuję plik cookie, który nie wydaje się być zachowany w moim HttpClient, mimo że dokumenty sugerują, że właśnie to powinno się stać.

Oto niektóre z moich kodu:

DefaultHttpClient httpclient = new DefaultHttpClient(); 
HttpPost httpost = new HttpPost(LOGIN_URL); 

List<NameValuePair> nvps = new ArrayList<NameValuePair>(); 
nvps.add(new BasicNameValuePair(USER_FIELD, login)); 
nvps.add(new BasicNameValuePair(PASS_FIELD, pw)); 
nvps.add(new BasicNameValuePair(REMEMBERME, "on")); 

httpost.setEntity(new UrlEncodedFormEntity(nvps, HTTP.UTF_8)); 

HttpResponse response = httpclient.execute(httpost); 
HttpEntity entity = response.getEntity(); 

if (entity != null) { 
    entity.consumeContent(); 
} 

List<Cookie> cookies = httpclient.getCookieStore().getCookies(); 

Kiedy wyjście I zawartość "cookies", wszystko wydaje się w porządku (I odbieranie sesji):

- [version: 0][name: ASP.NET_SessionId][value: xxx][domain: xxx][path: /][expiry: null]

Jak zrozumiałem, plik cookie/sesja zostanie zachowany i użyty w moim HttpClient, o ile go nie zamknę.

Podczas czytania następna strona (który jest ograniczony), przy użyciu tego kodu:

HttpGet httpget2 = new HttpGet(RESTRICTED_URL); 
response = httpclient.execute(httpget2); 
entity = response.getEntity(); 
InputStream data = entity.getContent(); 
// data will be parsed here 
if (entity != null) { 
    entity.consumeContent(); 
} 
// connection will be closed afterwards 

Jeżeli wyjście I odpowiedź GET-życzenie (za pomocą response.getStatusLine()) pojawia się komunikat "200 OK", ale parsowanie zwróconej strony pokazuje, że logowanie zostało utracone (pobieram tylko formularz logowania).

Każda pomoc jest doceniana.

Odpowiedz

1

Zakładając, że obiekt httpclient jest taka sama w obu przypadkach i przy założeniu, że RESTRICTED_URL jest w tej samej domenie co LOGIN_URL, wtedy myślę, że to, co masz powinno działać.

Możesz chcieć użyć Wiresharka lub serwera proxy lub czegoś do zbadania żądanych żądań HTTP, aby sprawdzić, czy plik cookie jest faktycznie dołączany do żądania. Być może plik cookie jest dołączany, aw takim przypadku jest coś złego, co powoduje, że twoja druga prośba o niepowodzenie.

+0

'httpclient' jest taka sama dla wszystkich żądań i adresy URL są zarówno na samej domeny (zarówno bez SSL). Spróbuję Wireshark, aby dowiedzieć się, co jest wysyłane, dzięki za podpowiedź. – Select0r

+0

Próbowałem już: plik cookie jest dołączony do drugiego żądania (GET) i otrzymuję komunikat "Znaleziono 302", który wyświetli ekran logowania. – Select0r

+1

@ Select0r: brzmi jak coś innego jest wtedy nie tak z drugim żądaniem (np. Serwer oczekuje nagłówka 'Referer:'). – CommonsWare

2

W aplikacji, do której muszę się zalogować. Najpierw muszę uruchomić GET, a następnie POST, a następnie GET ponownie. Pierwsze pobranie utworzy identyfikator Jsession dla mojego połączenia. POST dokona uwierzytelnienia mojego ID, a następnie oryginalny GET zwróci prawdziwą treść.

Poniższy kod jest dla aplikacji działającej w JBoss

public boolean login() { 
    HttpGet httpGet = new HttpGet( "http://localhost:8080/gwt-console-server/rs/identity/secure/sid/"); 
    HttpPost httpPost = new HttpPost("http://localhost:8080/gwt-console-server/rs/identity/secure/j_security_check"); 
    HttpResponse response = null; 

    List<NameValuePair> nvps = new ArrayList<NameValuePair>(); 
    nvps.add(new BasicNameValuePair(USER_FIELD, userName)); 
    nvps.add(new BasicNameValuePair(PASS_FIELD, password)); 

    try { 
     httpPost.setEntity(new UrlEncodedFormEntity(nvps, HTTP.UTF_8)); 

     response = httpClient.execute(httpGet); 
     EntityUtils.consume(response.getEntity()); 

     response = httpClient.execute(httpPost); 
     EntityUtils.consume(response.getEntity()); 

     response = httpClient.execute(httpGet); 
     String sessionId =EntityUtils.toString(response.getEntity()); 

     String cookieId =""; 
     List<Cookie> cookies = ((AbstractHttpClient) httpClient).getCookieStore().getCookies(); 
     for (Cookie cookie: cookies){ 
      if (cookie.getName().equals("JSESSIONID")){ 
       cookieId = cookie.getValue(); 
      } 
     } 

     if(sessionId!= null && sessionId.equals(cookieId)){ 
      return true; 
     } 
    } catch (ClientProtocolException e) { 
     // TODO Auto-generated catch block 
     e.printStackTrace(); 
    } catch (IOException e) { 
     // TODO Auto-generated catch block 
     e.printStackTrace(); 
    } 
    return false; 
} 
0

Można zrobić to w ten sposób, choć to raczej obejście.

@Override 
public void onCreate(Bundle savedInstanceState) { 
    super.onCreate(savedInstanceState); 
    setContentView(R.layout.activity_main); 

    WebView webv = (WebView)findViewById(R.id.MainActivity_webview);   
    webv.setWebViewClient(new WebViewClient(){ 
      @Override 
      public boolean shouldOverrideUrlLoading(WebView view, String url) { 
       view.loadUrl(url); 
       return true; 
      } 
    }); 

    String postData = FIELD_NAME_LOGIN + "=" + LOGIN + 
      "&" + FIELD_NAME_PASSWD + "=" + PASSWD; 

    // this line logs you in and you stay logged in 
    // I suppose it works this way because in this case WebView handles cookies itself 
    webv.postUrl(URL, EncodingUtils.getBytes(postData, "utf-8")); 
} 
1

Trzeba dokonać DefaultHttpClient httpclient z Singleton tak sessioncookie że trzeba jeszcze posiadać sesji z logowaniem.

Jest to klasa Mainactivity:

public static DefaultHttpClient httpClient; 

@Override 
public void onCreate(Bundle savedInstanceState) { 
    super.onCreate(savedInstanceState); 
    RequestPage request = new RequestPage(); 
    request.post("http://www.example.com/login.php"); 

    RequestPage requestProfile =new RequestPage(); 
    requestProfile.post("http://www.example.com/profile.php"); 
} 

i jest to klasa RequestPage:

private InputStream post(String url){ 
    String paramUsername = "username"; 
    String paramPassword = "pass"; 

    if(MainActivity.httpClient==null){ 
     MainActivity.httpClient = new DefaultHttpClient(); 
    } 
    DefaultHttpClient httpClient = MainActivity.httpClient; 

    // In a POST request, we don't pass the values in the URL. 
    //Therefore we use only the web page URL as the parameter of the HttpPost argument 
    HttpPost httpPost = new HttpPost(url); 

      // Because we are not passing values over the URL, we should have a mechanism to pass the values that can be 
    //uniquely separate by the other end. 
    //To achieve that we use BasicNameValuePair    
    //Things we need to pass with the POST request 
    BasicNameValuePair usernameBasicNameValuePair = new BasicNameValuePair("username", paramUsername); 
    BasicNameValuePair passwordBasicNameValuePAir = new BasicNameValuePair("password", paramPassword); 

    // We add the content that we want to pass with the POST request to as name-value pairs 
    //Now we put those sending details to an ArrayList with type safe of NameValuePair 
    List<NameValuePair> nameValuePairList = new ArrayList<NameValuePair>(); 
    nameValuePairList.add(usernameBasicNameValuePair); 
    nameValuePairList.add(passwordBasicNameValuePAir); 

    try { 
     // UrlEncodedFormEntity is an entity composed of a list of url-encoded pairs. 
     //This is typically useful while sending an HTTP POST request. 
     UrlEncodedFormEntity urlEncodedFormEntity = new UrlEncodedFormEntity(nameValuePairList); 

     // setEntity() hands the entity (here it is urlEncodedFormEntity) to the request. 
     httpPost.setEntity(urlEncodedFormEntity); 

     try { 
      // HttpResponse is an interface just like HttpPost. 
      //Therefore we can't initialize them 
      HttpResponse httpResponse = httpClient.execute(httpPost); 

      // According to the JAVA API, InputStream constructor do nothing. 
      //So we can't initialize InputStream although it is not an interface 


      return httpResponse.getEntity().getContent(); 

     } catch (ClientProtocolException cpe) { 
      System.out.println("First Exception caz of HttpResponese :" + cpe); 
      cpe.printStackTrace(); 
     } catch (IOException ioe) { 
      System.out.println("Second Exception caz of HttpResponse :" + ioe); 
      ioe.printStackTrace(); 
     } 

    } catch (UnsupportedEncodingException uee) { 
     System.out.println("An Exception given because of UrlEncodedFormEntity argument :" + uee); 
     uee.printStackTrace(); 
    } 

    return null; 
} 
Powiązane problemy