2009-03-24 13 views
110

Me gustaría realizar una solicitud http a un servidor remoto mientras se manejan las cookies (por ej., Almacenar las cookies enviadas por el servidor y enviarlas cuando realice las siguientes). Sería bueno preservar todas y cada una de las cookies, pero realmente la única que me importa es la cookie de sesión.¿Cómo realizo una solicitud http usando cookies en Android?

Con java.net, parece que la forma preferida de hacerlo es usando java.net.CookieHandler (clase base abstracta) y java.net.CookieManager (implementación concreta). Android tiene java.net.CookieHandler, pero no parece tener java.net.CookieManager.

Pude codificar todo a mano inspeccionando encabezados http, pero parece que debe haber una manera más fácil.

¿Cuál es la forma correcta de realizar solicitudes http en Android conservando cookies?

+3

Así como una nota más más de dos años después: 'java.net.CookieManager' ahora es compatible con Android desde la versión 2.3 (API nivel 9): http://developer.android.com/reference/java/net/CookieManager.html – Slauma

+0

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

Respuesta

89

Resulta que los barcos Google Android con Apache HttpClient 4.0, y yo era capaz de encontrar la manera de hacerlo utilizando el "inicio de sesión de formulario basado" ejemplo en el 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

¿puedo saber cómo configurar las cookies en la URL de solicitud para verificar si la sesión es válida o no? – Praveen

+0

GRACIAS por presentarme a BasicNameValuePairs. Ellos me ayudaron. – bhekman

+2

Me sale 'El método getCookieStore() no está definido para el tipo HttpClient', ¿Tengo que cambiar a' List cookies = ((AbstractHttpClient) httpclient) .getCookieStore(). GetCookies(); '? Porque si lo hago, funciona. –

0

No trabajo con Google Android, pero creo que encontrará que no es tan difícil hacerlo funcionar. Si lee the relevant bit of the java tutorial, verá que un manipulador de cookies registrado recibe devoluciones de llamada del código HTTP.

Entonces, si no hay un valor predeterminado (¿ha marcado si CookieHandler.getDefault() realmente es nulo?) Entonces simplemente puede extender CookieHandler, implementar put/get y hacer que funcione de forma prácticamente automática. Asegúrese de considerar el acceso simultáneo y similares si sigue esa ruta.

editar: Obviamente, tendría que establecer una instancia de su implementación personalizada como el controlador predeterminado a través de CookieHandler.setDefault() para recibir las devoluciones de llamada. Olvidé mencionar eso.

8

Una cookie es simplemente otro encabezado HTTP. Siempre puede configurarlo mientras realiza una llamada HTTP con la biblioteca apache o con HTTPUrlConnection. De cualquier manera, debería poder leer y establecer cookies HTTP de esta manera. Para obtener más información, puede leer this article.

Puedo compartir mi paz de código para demostrar lo fácil que puede hacerlo.

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

Esto me ayuda mucho, +1 get.setHeader ("Cookie", "PHPSESSID =" + token + ";"); haz el trabajo – Oussaki

+0

¡¡Funciona bien !! –

+0

@Hesam: unfortunatley módulo de apache de Android desaprobado. Entonces, en este momento su respuesta no es útil. ¿Hay alguna otra manera de hacer esto con HttpURLConnection? –

3

Desde biblioteca de Apache está en desuso, para aquellos que quieran utilizar HttpURLConncetion, escribí esta clase para enviar Obtener y petición POST con la ayuda de 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! Me ayudó mucho ! Ahora, me preguntaba si quería guardar la cookie para que esté disponible si el usuario eliminó la aplicación y la lanzó nuevamente, qué debería exactamente almacenar y dónde (cómo) –

Cuestiones relacionadas