¿Cómo realizo una solicitud http usando cookies en Android?

Me gustaría hacer una solicitud http a un servidor remoto mientras manejo 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.

Con java.net, parece que la forma preferida de hacerlo es usar 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.

Podría codificarlo 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 las cookies?

Resulta que Google Android se envía con Apache HttpClient 4.0, y pude descifrar cómo hacerlo usando el ejemplo de “inicio de sesión basado en el formulario” en los documentos de HttpClient :

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 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  nvps = new ArrayList (); 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(); } } 

Una cookie es solo 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.

Puedes leer este artículo para más información.

Puedo compartir mi paz de código para demostrar lo fácil que puedes 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; } 

Como la biblioteca Apache está en desuso , para aquellos que quieran usar HttpURLConncetion , escribí esta clase para enviar Get y Post Request con la ayuda de esta respuesta :

 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> headerFields = conn.getHeaderFields(); List 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> headerFields = con.getHeaderFields(); List 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; } } 

No trabajo con Google Android, pero creo que encontrarás que no es tan difícil hacerlo funcionar. Si lees el fragmento relevante del tutorial de Java , verás que un manipulador de cookies registrado obtiene devoluciones de llamadas del código HTTP.

Entonces, si no hay un valor predeterminado (¿has marcado si CookieHandler.getDefault() realmente es nulo?) Entonces simplemente puedes 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.