2009-03-24 4 views
110

Vorrei fare una richiesta http a un server remoto mentre gestisco correttamente i cookie (ad esempio, memorizzare i cookie inviati dal server e inviare quei cookie quando faccio richieste successive). Sarebbe bello conservare tutti i cookie, ma in realtà l'unico a cui tengo è il cookie di sessione.Come faccio a fare una richiesta http utilizzando i cookie su Android?

Con java.net, sembra che il modo migliore per farlo sia utilizzare java.net.CookieHandler (classe base astratta) e java.net.CookieManager (implementazione concreta). Android ha java.net.CookieHandler, ma non sembra avere java.net.CookieManager.

Potrei codificarlo tutto a mano ispezionando le intestazioni http, ma sembra che ci debba essere un modo più semplice.

Qual è il modo corretto di effettuare richieste HTTP su Android conservando i cookie?

+3

Proprio come una nota più di due anni dopo: 'java.net.CookieManager' è ora supportato in Android dalla versione 2.3 (livello API 9): http://developer.android.com/reference/java/net/CookieManager.html – Slauma

+0

Hai provato [ org.apache.http.cookie] (http://developer.android.com/reference/org/apache/http/cookie/package-summary.html)? –

risposta

89

Si scopre che le navi di Google Android con Apache HttpClient 4.0, e sono stato in grado di capire come farlo utilizzando il "accesso di modulo basato" esempio nel HttpClient docs:

http://svn.apache.org/repos/asf/httpcomponents/httpclient/trunk/httpclient/src/examples/org/apache/http/examples/client/ClientFormLogin.java


import java.util.ArrayList; 
import java.util.List; 
import org.apache.http.HttpEntity; 
import org.apache.http.HttpResponse; 
import org.apache.http.NameValuePair; 
import org.apache.http.client.entity.UrlEncodedFormEntity; 
import org.apache.http.client.methods.HttpGet; 
import org.apache.http.client.methods.HttpPost; 
import org.apache.http.cookie.Cookie; 
import org.apache.http.impl.client.DefaultHttpClient; 
import org.apache.http.message.BasicNameValuePair; 
import org.apache.http.protocol.HTTP; 

/** 
* A example that demonstrates how HttpClient APIs can be used to perform 
* form-based logon. 
*/ 
public class ClientFormLogin { 

    public static void main(String[] args) throws Exception { 

     DefaultHttpClient httpclient = new DefaultHttpClient(); 

     HttpGet httpget = new HttpGet("https://portal.sun.com/portal/dt"); 

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

     System.out.println("Login form get: " + response.getStatusLine()); 
     if (entity != null) { 
      entity.consumeContent(); 
     } 
     System.out.println("Initial set of cookies:"); 
     List<Cookie> cookies = httpclient.getCookieStore().getCookies(); 
     if (cookies.isEmpty()) { 
      System.out.println("None"); 
     } else { 
      for (int i = 0; i < cookies.size(); i++) { 
       System.out.println("- " + cookies.get(i).toString()); 
      } 
     } 

     HttpPost httpost = new HttpPost("https://portal.sun.com/amserver/UI/Login?" + 
       "org=self_registered_users&" + 
       "goto=/portal/dt&" + 
       "gotoOnFail=/portal/dt?error=true"); 

     List <NameValuePair> nvps = new ArrayList <NameValuePair>(); 
     nvps.add(new BasicNameValuePair("IDToken1", "username")); 
     nvps.add(new BasicNameValuePair("IDToken2", "password")); 

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

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

     System.out.println("Login form get: " + response.getStatusLine()); 
     if (entity != null) { 
      entity.consumeContent(); 
     } 

     System.out.println("Post logon cookies:"); 
     cookies = httpclient.getCookieStore().getCookies(); 
     if (cookies.isEmpty()) { 
      System.out.println("None"); 
     } else { 
      for (int i = 0; i < cookies.size(); i++) { 
       System.out.println("- " + cookies.get(i).toString()); 
      } 
     } 

     // When HttpClient instance is no longer needed, 
     // shut down the connection manager to ensure 
     // immediate deallocation of all system resources 
     httpclient.getConnectionManager().shutdown();   
    } 
} 
+11

posso sapere come impostare i cookie sull'URL di richiesta per verificare se la sessione è valida o no? – Praveen

+0

GRAZIE per avermi presentato BasicNameValuePairs. Mi hanno aiutato. – bhekman

+2

Ottengo 'Il metodo getCookieStore() non è definito per il tipo HttpClient', Devo passare a' Elenco cookies = ((AbstractHttpClient) httpclient) .getCookieStore(). GetCookies(); '? Perché se lo faccio, funziona. –

0

Non lavoro con google android ma penso che troverete che non è così difficile farlo funzionare. Se leggi the relevant bit of the java tutorial vedrai che un cookiehandler registrato riceve le richiamate dal codice HTTP.

Quindi, se non esiste un valore predefinito (hai controllato se CookieHandler.getDefault() è veramente nullo?), Puoi semplicemente estendere CookieHandler, implementare put/get e farlo funzionare in modo automatico. Assicurati di considerare l'accesso simultaneo e simili se segui questa strada.

modifica: Ovviamente è necessario impostare un'istanza dell'implementazione personalizzata come gestore predefinito tramite CookieHandler.setDefault() per ricevere le richiamate. Ho dimenticato di dirlo.

8

Un cookie è solo un'altra intestazione HTTP. È sempre possibile impostarlo mentre si effettua una chiamata HTTP con la libreria apache o con HTTPUrlConnection. In ogni caso dovresti essere in grado di leggere e impostare i cookie HTTP in questo modo.

È possibile leggere this article per ulteriori informazioni.

Posso condividere la mia tranquillità del codice per dimostrare quanto sia facile realizzarlo.

public static String getServerResponseByHttpGet(String url, String token) { 

     try { 
      HttpClient client = new DefaultHttpClient(); 
      HttpGet get = new HttpGet(url); 
      get.setHeader("Cookie", "PHPSESSID=" + token + ";"); 
      Log.d(TAG, "Try to open => " + url); 

      HttpResponse httpResponse = client.execute(get); 
      int connectionStatusCode = httpResponse.getStatusLine().getStatusCode(); 
      Log.d(TAG, "Connection code: " + connectionStatusCode + " for request: " + url); 

      HttpEntity entity = httpResponse.getEntity(); 
      String serverResponse = EntityUtils.toString(entity); 
      Log.d(TAG, "Server response for request " + url + " => " + serverResponse); 

      if(!isStatusOk(connectionStatusCode)) 
       return null; 

      return serverResponse; 

     } catch (UnsupportedEncodingException e) { 
      e.printStackTrace(); 
     } catch (ClientProtocolException e) { 
      e.printStackTrace(); 
     } catch (IOException e) { 
      e.printStackTrace(); 
     } catch (IllegalArgumentException e) { 
      e.printStackTrace(); 
     } catch (Exception e) { 
      e.printStackTrace(); 
     } 

     return null; 
    } 
+0

Questo mi aiuta molto, +1 get.setHeader ("Cookie", "PHPSESSID =" + token + ";"); fare il lavoro – Oussaki

+0

Funziona benissimo !! –

+0

@Hesam: sfortunatamente un modulo apache deprecato da Android. Quindi in questo momento la sua risposta non è utile. C'è un altro modo per farlo con HttpURLConnection? –

3

Dal libreria Apache è deprecato, per coloro che vogliono usare HttpURLConncetion, ho scritto questa classe per inviare GET e POST richiesta con l'aiuto di this answer:

public class WebService { 

static final String COOKIES_HEADER = "Set-Cookie"; 
static final String COOKIE = "Cookie"; 

static CookieManager msCookieManager = new CookieManager(); 

private static int responseCode; 

public static String sendPost(String requestURL, String urlParameters) { 

    URL url; 
    String response = ""; 
    try { 
     url = new URL(requestURL); 

     HttpURLConnection conn = (HttpURLConnection) url.openConnection(); 
     conn.setReadTimeout(15000); 
     conn.setConnectTimeout(15000); 
     conn.setRequestMethod("POST"); 

     conn.setRequestProperty("Content-Type", "application/json; charset=utf-8"); 

     if (msCookieManager.getCookieStore().getCookies().size() > 0) { 
      //While joining the Cookies, use ',' or ';' as needed. Most of the server are using ';' 
      conn.setRequestProperty(COOKIE , 
        TextUtils.join(";", msCookieManager.getCookieStore().getCookies())); 
     } 

     conn.setDoInput(true); 
     conn.setDoOutput(true); 

     OutputStream os = conn.getOutputStream(); 
     BufferedWriter writer = new BufferedWriter(
       new OutputStreamWriter(os, "UTF-8")); 

     if (urlParameters != null) { 
      writer.write(urlParameters); 
     } 
     writer.flush(); 
     writer.close(); 
     os.close(); 

     Map<String, List<String>> headerFields = conn.getHeaderFields(); 
     List<String> cookiesHeader = headerFields.get(COOKIES_HEADER); 

     if (cookiesHeader != null) { 
      for (String cookie : cookiesHeader) { 
       msCookieManager.getCookieStore().add(null, HttpCookie.parse(cookie).get(0)); 
      } 
     } 

     setResponseCode(conn.getResponseCode()); 

     if (getResponseCode() == HttpsURLConnection.HTTP_OK) { 

      String line; 
      BufferedReader br = new BufferedReader(new InputStreamReader(conn.getInputStream())); 
      while ((line = br.readLine()) != null) { 
       response += line; 
      } 
     } else { 
      response = ""; 
     } 
    } catch (Exception e) { 
     e.printStackTrace(); 
    } 

    return response; 
} 


// HTTP GET request 
public static String sendGet(String url) throws Exception { 

    URL obj = new URL(url); 
    HttpURLConnection con = (HttpURLConnection) obj.openConnection(); 

    // optional default is GET 
    con.setRequestMethod("GET"); 

    //add request header 
    con.setRequestProperty("User-Agent", "Mozilla"); 
    /* 
    * https://stackoverflow.com/questions/16150089/how-to-handle-cookies-in-httpurlconnection-using-cookiemanager 
    * Get Cookies form cookieManager and load them to connection: 
    */ 
    if (msCookieManager.getCookieStore().getCookies().size() > 0) { 
     //While joining the Cookies, use ',' or ';' as needed. Most of the server are using ';' 
     con.setRequestProperty(COOKIE , 
       TextUtils.join(";", msCookieManager.getCookieStore().getCookies())); 
    } 

    /* 
    * https://stackoverflow.com/questions/16150089/how-to-handle-cookies-in-httpurlconnection-using-cookiemanager 
    * Get Cookies form response header and load them to cookieManager: 
    */ 
    Map<String, List<String>> headerFields = con.getHeaderFields(); 
    List<String> cookiesHeader = headerFields.get(COOKIES_HEADER); 
    if (cookiesHeader != null) { 
     for (String cookie : cookiesHeader) { 
      msCookieManager.getCookieStore().add(null, HttpCookie.parse(cookie).get(0)); 
     } 
    } 


    int responseCode = con.getResponseCode(); 

    BufferedReader in = new BufferedReader(
      new InputStreamReader(con.getInputStream())); 
    String inputLine; 
    StringBuffer response = new StringBuffer(); 

    while ((inputLine = in.readLine()) != null) { 
     response.append(inputLine); 
    } 
    in.close(); 

    return response.toString(); 
} 

public static void setResponseCode(int responseCode) { 
    WebService.responseCode = responseCode; 
    Log.i("Milad", "responseCode" + responseCode); 
} 


public static int getResponseCode() { 
    return responseCode; 
} 
} 
+2

Nice Class Milad! Mi ha aiutato molto! Ora, mi stavo chiedendo, se volevo salvare il cookie affinché fosse disponibile se l'utente ha ucciso l'app e l'ha lanciato di nuovo, cosa dovrei esattamente archiviare e dove (come) –