Android: Persistencia de la sesión de servidor mediante cookie al realizar llamadas HTTP

Las sesiones del lado del servidor se almacenan en la base de datos y se mantienen mediante cookies. Por lo tanto, cada cliente debe venir con una cookie válida que coincida con una sesión en la base de datos.

Y en Android:

DefaultHttpClient client = new DefaultHttpClient(); HttpPost httppost = new HttpPost(url); HttpResponse response = client.execute(httppost); 

Si utilizo el mismo cliente para todas las llamadas al servidor, el cliente se encargará de estas cookies.

Pero el problema es que, cuando el cliente se destruye, debido a la memoria que necesita el dispositivo, las cookies se pierden y las llamadas de servidor subsiguientes no funcionan.

¿Hay una manera de hacer el HttpClient persistente? O lo que es la forma habitual de mantener las cookies en el lado de Android.

La forma "correcta" de hacerlo es implementar un CookieHandler: http://developer.android.com/reference/java/net/CookieHandler.html

La forma más básica de hacer esto es extender la aplicación y poner esto en sus aplicaciones onCreate ():

 CookieHandler.setDefault(new CookieManager()); 

NOTA: Esto sólo implementará un DEFAULT CookieManger. El CookieManger predeterminado administrará las cookies para todas sus solicitudes HTTP durante una sesión específica de su aplicación. Sin embargo, no tiene ningún medio de cookies persistentes sobre usos posteriores de la aplicación.

Para ello, necesitará escribir su propio gestor de cookies mediante la implementación de CookieStore: http://developer.android.com/reference/java/net/CookieStore.html

He aquí un ejemplo de una implementación de CookieStore que usé en una aplicación que se encuentra actualmente en Google Play Store:

 package com.touchvision.util; import java.net.CookieStore; import java.net.HttpCookie; import java.net.URI; import java.net.URISyntaxException; import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.Set; import android.content.Context; import android.content.SharedPreferences; import android.content.SharedPreferences.Editor; import android.util.Log; import com.touchvision.Config; /* * This is a custom cookie storage for the application. This * will store all the cookies to the shared preferences so that it persists * across application restarts. */ public class TvCookieStore implements CookieStore { private static final String LOGTAG = "TV-TvCookieStore"; /* * The memory storage of the cookies */ private Map<String, Map<String,String>> mapCookies = new HashMap<String, Map<String,String>>(); /* * The instance of the shared preferences */ private final SharedPreferences sharedPrefs; /* * @see java.net.CookieStore#add(java.net.URI, java.net.HttpCookie) */ public void add(URI uri, HttpCookie cookie) { String domain = cookie.getDomain(); // Log.i(LOGTAG, "adding ( " + domain +", " + cookie.toString() ); Map<String,String> cookies = mapCookies.get(domain); if (cookies == null) { cookies = new HashMap<String, String>(); mapCookies.put(domain, cookies); } cookies.put(cookie.getName(), cookie.getValue()); if (cookie.getName().startsWith("SPRING_SECURITY") && !cookie.getValue().equals("")){ // Log.i(LOGTAG, "Saving rememberMeCookie = " + cookie.getValue() ); // Update in Shared Preferences Editor e = sharedPrefs.edit(); e.putString(Config.PREF_SPRING_SECURITY_COOKIE, cookie.toString()); e.commit(); // save changes } } /* * Constructor * * @param ctxContext the context of the Activity */ public TvCookieStore(Context ctxContext) { // Log.i(LOGTAG, "constructor()"); sharedPrefs = ctxContext.getSharedPreferences(Config.SHARED_PREF_NAME, Context.MODE_PRIVATE); } /* * @see java.net.CookieStore#get(java.net.URI) */ public List<HttpCookie> get(URI uri) { List<HttpCookie> cookieList = new ArrayList<HttpCookie>(); String domain = uri.getHost(); // Log.i(LOGTAG, "getting ( " + domain +" )" ); Map<String,String> cookies = mapCookies.get(domain); if (cookies == null) { cookies = new HashMap<String, String>(); mapCookies.put(domain, cookies); } for (Map.Entry<String, String> entry : cookies.entrySet()) { cookieList.add(new HttpCookie(entry.getKey(), entry.getValue())); // Log.i(LOGTAG, "returning cookie: " + entry.getKey() + "="+ entry.getValue()); } return cookieList; } /* * @see java.net.CookieStore#removeAll() */ public boolean removeAll() { // Log.i(LOGTAG, "removeAll()" ); mapCookies.clear(); return true; } /* * @see java.net.CookieStore#getCookies() */ public List<HttpCookie> getCookies() { Log.i(LOGTAG, "getCookies()" ); Set<String> mapKeys = mapCookies.keySet(); List<HttpCookie> result = new ArrayList<HttpCookie>(); for (String key : mapKeys) { Map<String,String> cookies = mapCookies.get(key); for (Map.Entry<String, String> entry : cookies.entrySet()) { result.add(new HttpCookie(entry.getKey(), entry.getValue())); Log.i(LOGTAG, "returning cookie: " + entry.getKey() + "="+ entry.getValue()); } } return result; } /* * @see java.net.CookieStore#getURIs() */ public List<URI> getURIs() { Log.i(LOGTAG, "getURIs()" ); Set<String> keys = mapCookies.keySet(); List<URI> uris = new ArrayList<URI>(keys.size()); for (String key : keys){ URI uri = null; try { uri = new URI(key); } catch (URISyntaxException e) { e.printStackTrace(); } uris.add(uri); } return uris; } /* * @see java.net.CookieStore#remove(java.net.URI, java.net.HttpCookie) */ public boolean remove(URI uri, HttpCookie cookie) { String domain = cookie.getDomain(); Log.i(LOGTAG, "remove( " + domain +", " + cookie.toString() ); Map<String,String> lstCookies = mapCookies.get(domain); if (lstCookies == null) return false; return lstCookies.remove(cookie.getName()) != null; } } 

La CookieStore personalizada anterior utiliza SharedPreferences para conservar las cookies. Implementar la clase anterior similar a cómo implementar el CookieManager predeterminado en su clase de aplicación, pero la línea sería así:

 CookieHandler.setDefault( new CookieManager( new TvCookieStore(this), CookiePolicy.ACCEPT_ALL)); 

Como se puede ver, la única cookie que realmente me importó persistir fue la Spring Security Cookie (estábamos usando Spring Framework en el lado del servidor). Su código obviamente será diferente para dar cuenta de sus necesidades específicas.

Otra nota rápida: he intentado incontables veces para hacer lo que estás haciendo y manejar la persistencia de las cookies dentro de mi clase de cliente http. No eran más que dolores de cabeza. Dar a esta estrategia una oportunidad.

Esto puede no ser cookies, pero tal vez helphttp: //developer.android.com/reference/android/accounts/package-summary.html

Intente abajo el código:

 public static List<Cookie> cookies; cookies = httpclient.getCookieStore().getCookies(); if (cookies != null) { CookieSyncManager.createInstance(MainActivity.activity); CookieManager cookieManager = CookieManager.getInstance(); cookieManager.setAcceptCookie(true); for (Cookie cookie : cookies) { Cookie sessionInfo = cookie; String cookieString = sessionInfo.getName() + "=" + sessionInfo.getValue() + "; domain=" + sessionInfo.getDomain(); cookieManager.setCookie( domainUrl,cookieString); CookieSyncManager.getInstance().sync(); } } 

Prueba de esta manera Espero que esto te ayude

 public static List<Cookie> cookies; public static List<Cookie> sync(String url) { CookieManager cookieManager = CookieManager.getInstance(); if (cookieManager == null) return null; RFC2109Spec cookieSpec = new RFC2109Spec(); String rawCookieHeader = null; try { URL parsedURL = new URL(url); rawCookieHeader = cookieManager.getCookie(parsedURL.getHost()); if (rawCookieHeader == null) return null; int port = parsedURL.getPort() == -1 ? parsedURL.getDefaultPort() : parsedURL.getPort(); CookieOrigin cookieOrigin = new CookieOrigin(parsedURL.getHost(), port, "/", false); List<Cookie> cookies = cookieSpec.parse(new BasicHeader( "set-cookie", rawCookieHeader), cookieOrigin); return cookies; } catch (Exception e) { } return null; } public void sync() { if (cookies != null) { CookieManager cookieManager = CookieManager.getInstance(); cookieManager.setAcceptCookie(true); for (Cookie cookie : cookies) { Cookie sessionInfo = cookie; String cookieString = sessionInfo.getName() + "=" + sessionInfo.getValue() + "; domain=" + sessionInfo.getDomain(); cookieManager.setCookie("yourDomainUrl", cookieString); CookieSyncManager.getInstance().sync(); } } } public static DefaultHttpClient getHttpclient() { HttpParams httpParameters = new BasicHttpParams(); HttpConnectionParams.setConnectionTimeout(httpParameters, 30000); HttpConnectionParams.setSoTimeout(httpParameters, 30000); DefaultHttpClient httpclient = new DefaultHttpClient(httpParameters); if (cookies != null) { int size = cookies.size(); for (int i = 0; i < size; i++) { httpclient.getCookieStore().addCookie(cookies.get(i)); } } else { cookies = sync("yourDomain"); if (cookies != null) { int size = cookies.size(); for (int i = 0; i < size; i++) { httpclient.getCookieStore().addCookie(cookies.get(i)); } } } httpclient.getParams().setParameter(CoreProtocolPNames.USER_AGENT, "android"); return httpclient; } 

¿Cómo utilizar?

 DefaultHttpClient client =getHttpclient(); HttpPost httppost = new HttpPost(url); HttpResponse response = client.execute(httppost); try { cookies = httpclient.getCookieStore().getCookies(); sync(); } catch (Exception e) { } 
  • Reemplazo de código de Facebook obsoleto para Android
  • Uso de cookies con solicitudes de Retrofit Robospice
  • Parámetros incorrectos: BadParametersError: Los parámetros eran incorrectos. Queríamos capacidades requeridas en la cuadrícula de Selenium mientras ejecuta Appium
  • Salir de una sesión de LinkedIn en Android
  • Permiso de denegación: proveedor de apertura com.android.providers.contacts.ContactsProvider2
  • Disminuir la verbosidad del registro interno de ORMlite o deshabilitarla
  • Inicio de sesión de Android - Mejor implementación
  • Android: inicia sesión en el sitio web y conserva sesión / cookie mediante DefaultHttpClient
  • Estrategia de la aplicación de Android para realizar un seguimiento de una sesión de inicio de sesión
  • Implementar reintento Cuando la lógica
  • ¿Cómo mantener el inicio de sesión del servidor en toda la aplicación nativa de Android?
  • FlipAndroid es un fan de Google para Android, Todo sobre Android Phones, Android Wear, Android Dev y Aplicaciones para Android Aplicaciones.