android http cookies android-webview httpurlconnection

Sincronización bidireccional para cookies entre HttpURLConnection(java.net.CookieManager) y WebView(android.webkit.CookieManager)



android-webview (1)

Implementé mi propia idea. En realidad es bastante genial. Creé mi propia implementación de java.net.CookieManager que reenvía todas las solicitudes al webkit de WebView, android.webkit.CookieManager . Esto significa que no se requiere sincronización y HttpURLConnection utiliza el mismo almacenamiento de cookies que WebViews.

Clase WebkitCookieManagerProxy:

import java.io.IOException; import java.net.CookieManager; import java.net.CookiePolicy; import java.net.CookieStore; import java.net.URI; import java.util.Arrays; import java.util.List; import java.util.Map; public class WebkitCookieManagerProxy extends CookieManager { private android.webkit.CookieManager webkitCookieManager; public WebkitCookieManagerProxy() { this(null, null); } public WebkitCookieManagerProxy(CookieStore store, CookiePolicy cookiePolicy) { super(null, cookiePolicy); this.webkitCookieManager = android.webkit.CookieManager.getInstance(); } @Override public void put(URI uri, Map<String, List<String>> responseHeaders) throws IOException { // make sure our args are valid if ((uri == null) || (responseHeaders == null)) return; // save our url once String url = uri.toString(); // go over the headers for (String headerKey : responseHeaders.keySet()) { // ignore headers which aren''t cookie related if ((headerKey == null) || !(headerKey.equalsIgnoreCase("Set-Cookie2") || headerKey.equalsIgnoreCase("Set-Cookie"))) continue; // process each of the headers for (String headerValue : responseHeaders.get(headerKey)) { this.webkitCookieManager.setCookie(url, headerValue); } } } @Override public Map<String, List<String>> get(URI uri, Map<String, List<String>> requestHeaders) throws IOException { // make sure our args are valid if ((uri == null) || (requestHeaders == null)) throw new IllegalArgumentException("Argument is null"); // save our url once String url = uri.toString(); // prepare our response Map<String, List<String>> res = new java.util.HashMap<String, List<String>>(); // get the cookie String cookie = this.webkitCookieManager.getCookie(url); // return it if (cookie != null) res.put("Cookie", Arrays.asList(cookie)); return res; } @Override public CookieStore getCookieStore() { // we don''t want anyone to work with this cookie store directly throw new UnsupportedOperationException(); } }

Y úsela haciendo esto en la inicialización de su aplicación:

android.webkit.CookieSyncManager.createInstance(appContext); // unrelated, just make sure cookies are generally allowed android.webkit.CookieManager.getInstance().setAcceptCookie(true); // magic starts here WebkitCookieManagerProxy coreCookieManager = new WebkitCookieManagerProxy(null, java.net.CookiePolicy.ACCEPT_ALL); java.net.CookieHandler.setDefault(coreCookieManager);

Pruebas

Mi prueba inicial muestra que esto está funcionando bien. Veo cookies compartidas entre WebViews y HttpURLConnection. Espero no tener problemas. Si prueba esto y descubre cualquier problema, por favor coméntelo.

Desafortunadamente, hay una gran cantidad de administradores de cookies para Android. Las cookies para HttpURLConnection son mantenidas por java.net.CookieManager y las cookies para WebView son mantenidas por android.webkit.CookieManager . Estos repositorios de cookies están separados y requieren sincronización manual.

Mi aplicación utiliza HttpURLConnections y muestra WebViews (es un híbrido HTML nativo). Naturalmente, quiero que ambos compartan todas las cookies, así que tendré una sesión transparente en todas partes.

Más específicamente:

  1. Cuando se establece / cambia una cookie en un HttpURLConnection, quiero que WebViews vea este cambio también.
  2. Cuando se establece / cambia una cookie en un WebView, quiero que las próximas HttpURLConnections también vean este cambio.

En pocas palabras: estoy buscando una sincronización bidireccional. O mejor aún, que ambos usen el mismo repositorio de cookies. Puede suponer que ambos están activos al mismo tiempo (como en pestañas diferentes).

Preguntas:

  1. ¿Hay alguna manera de hacer que ambos usen el mismo depósito de cookies?

  2. Si no, ¿cuál es la práctica recomendada para hacer la sincronización manual? ¿Cuándo exactamente debería sincronizar y cómo?

Pregunta relacionada: Esta question aborda un problema similar, pero solo implementa la sincronización en un sentido (HttpURLConnection -> WebView).

Mi mejor idea hasta ahora: realmente quiero evitar una sincronización manual, así que traté de pensar cómo hacer que ambos usen el mismo repositorio. Tal vez pueda crear mi propio controlador central que amplíe java.net.CookieManager . Lo estableceré como el controlador de cookies principal utilizando java.net.CookieHandler.setDefault() . Su implementación será un proxy para la instancia del controlador android.webkit.CookieManager (para cada función, simplemente accederé al administrador de webkit).