example - android cookie manager
Problema de cookies de Android WebView (12)
Tengo un servidor que envía a mi aplicación Android una cookie de sesión para ser utilizada para la comunicación autenticada. Estoy tratando de cargar un WebView con una URL que apunta a ese mismo servidor y estoy tratando de pasar la cookie de sesión para la autenticación. Estoy observando que funciona intermitentemente, pero no tengo idea de por qué. Utilizo la misma cookie de sesión para hacer otras llamadas en mi servidor y estas nunca fallan la autenticación. Solo observo este problema cuando trato de cargar una URL en un WebView, y esto no ocurre siempre. Muy frustrante.
A continuación está el código que estoy usando para hacer esto. Cualquier ayuda será apreciada.
String myUrl = ""http://mydomain.com/";
CookieSyncManager.createInstance(this);
CookieManager cookieManager = CookieManager.getInstance();
Cookie sessionCookie = getCookie();
if(sessionCookie != null){
String cookieString = sessionCookie.getName() +"="+sessionCookie.getValue()+"; domain="+sessionCookie.getDomain();
cookieManager.setCookie(myUrl, cookieString);
CookieSyncManager.getInstance().sync();
}
WebView webView = (WebView) findViewById(R.id.webview);
webView.getSettings().setBuiltInZoomControls(true);
webView.getSettings().setJavaScriptEnabled(true);
webView.setWebViewClient(new MyWebViewClient());
webView.loadUrl(myUrl);
Encontré esto también también. Esto es lo que hice.
En mi LoginActivity, dentro de mi AsyncTask, tengo lo siguiente:
CookieStoreHelper.cookieStore = new BasicCookieStore();
BasicHttpContext localContext = new BasicHttpContext();
localContext.setAttribute(ClientContext.COOKIE_STORE, CookieStoreHelper.cookieStore);
HttpResponse postResponse = client.execute(httpPost,localContext);
CookieStoreHelper.sessionCookie = CookieStoreHelper.cookieStore.getCookies();
// WHERE CookieStoreHelper.sessionCookie es otra clase que contiene la variable sessionCookie definida como List cookies; y cookieStore define como BasicCookieStore cookieStore;
Luego, en mi Fragmento, donde se encuentra mi WebView, tengo lo siguiente:
//DECLARE LIST OF COOKIE
List<Cookie> sessionCookie;
dentro de mi método o justo antes de configurar el WebViewClient ()
WebSettings settings = webView.getSettings();
settings.setJavaScriptEnabled(true);
webView.setScrollBarStyle(WebView.SCROLLBARS_OUTSIDE_OVERLAY);
sessionCookie = CookieStoreHelper.cookieStore.getCookies();
CookieSyncManager.createInstance(webView.getContext());
CookieSyncManager.getInstance().startSync();
CookieManager cookieManager = CookieManager.getInstance();
CookieManager.getInstance().setAcceptCookie(true);
if (sessionCookie != null) {
for(Cookie c: sessionCookie){
cookieManager.setCookie(CookieStoreHelper.DOMAIN, c.getName() + "=" + c.getValue());
}
CookieSyncManager.getInstance().sync();
}
webView.setWebViewClient(new WebViewClient() {
//AND SO ON, YOUR CODE
}
Consejo rápido: Instale Firebug en Firefox o use la consola de desarrollador en Chrome y pruebe primero su página web, capture las cookies y verifique el dominio para poder almacenarlo en algún lugar y asegurarse de que está configurando correctamente el dominio correcto.
Editar: editado CookieStoreHelper.cookies a CookieStoreHelper.sessionCookie
Este es un código de código funcional.
private void setCookie(DefaultHttpClient httpClient, String url) {
List<Cookie> cookies = httpClient.getCookieStore().getCookies();
if (cookies != null) {
CookieSyncManager.createInstance(context);
CookieManager cookieManager = CookieManager.getInstance();
cookieManager.setAcceptCookie(true);
for (int i = 0; i < cookies.size(); i++) {
Cookie cookie = cookies.get(i);
String cookieString = cookie.getName() + "=" + cookie.getValue();
cookieManager.setCookie(url, cookieString);
}
CookieSyncManager.getInstance().sync();
}
}
Aquí el httpclient es el objeto DefaultHttpClient que usaste en la solicitud HttpGet / HttpPost. También una cosa para asegurarse es el nombre y el valor de la cookie, se debe dar
String cookieString = cookie.getName() + "=" + cookie.getValue();
setCookie establecerá la cookie para la URL dada.
Gracias justingrammens ! Eso funcionó para mí, logré compartir la cookie dentro de mis peticiones de DefaultHttpClient y la actividad de WebView:
//------- Native request activity
private DefaultHttpClient httpClient;
public static Cookie cookie = null;
//After Login
List<Cookie> cookies = httpClient.getCookieStore().getCookies();
for (int i = 0; i < cookies.size(); i++) {
cookie = cookies.get(i);
}
//------- Web Browser activity
Cookie sessionCookie = myapp.cookie;
CookieSyncManager.createInstance(this);
CookieManager cookieManager = CookieManager.getInstance();
if (sessionCookie != null) {
cookieManager.removeSessionCookie();
String cookieString = sessionCookie.getName() + "=" + sessionCookie.getValue() + "; domain=" + sessionCookie.getDomain();
cookieManager.setCookie(myapp.domain, cookieString);
CookieSyncManager.getInstance().sync();
}
Gracias a Android por arruinar mi domingo. . . Aquí está lo que solucionó mis aplicaciones (después de iniciar su página web)
if ( Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP ) {
CookieManager cookieManager = CookieManager.getInstance();
cookieManager.setAcceptThirdPartyCookies( webView, true );
}
Debo decir que las respuestas anteriores probablemente funcionen, pero en mi situación, en el momento en que Android pasó v5 +, mi aplicación web android javascript ''apps'' murió.
Guardaría esa cookie de sesión como preferencia y repoblaré forzosamente el administrador de cookies con ella. Suena que la cookie de sesión no se conserva.
Mi código de trabajo
public View onCreateView(...){
mWebView = (WebView) view.findViewById(R.id.webview);
WebSettings webSettings = mWebView.getSettings();
webSettings.setJavaScriptEnabled(true);
...
...
...
CookieSyncManager.createInstance(mWebView.getContext());
CookieManager cookieManager = CookieManager.getInstance();
cookieManager.setAcceptCookie(true);
//cookieManager.removeSessionCookie(); // remove
cookieManager.removeAllCookie(); //remove
// Recommended "hack" with a delay between the removal and the installation of "Cookies"
SystemClock.sleep(1000);
cookieManager.setCookie("https://my.app.site.com/", "cookiename=" + value + "; path=/registration" + "; secure"); // ;
CookieSyncManager.getInstance().sync();
mWebView.loadUrl(sp.getString("url", "") + end_url);
return view;
}
Para depurar la consulta, "cookieManager.setCookie (....);" Te recomiendo que revises el contenido de la base de datos webviewCookiesChromium.db (almacenado en "/data/data/my.app.webview/database") Allí puedes ver la configuración correcta.
Deshabilitar "cookieManager.removeSessionCookie ();" y / o "cookieManager.removeAllCookie ();"
//cookieManager.removeSessionCookie();
// and/or
//cookieManager.removeAllCookie();"
Compare el valor establecido con los que establece el navegador. Ajuste la solicitud para la instalación de las cookies antes de que el navegador "flags" no esté instalado se ajustará a lo que decida. Encontré que una consulta puede ser "banderas":
// You may want to add the secure flag for https:
+ "; secure"
// In case you wish to convert session cookies to have an expiration:
+ "; expires=Thu, 01-Jan-2037 00:00:10 GMT"
// These flags I found in the database:
+ "; path=/registration"
+ "; domain=my.app.site.com"
No use su url en bruto
En lugar de:
cookieManager.setCookie(myUrl, cookieString);
Úselo así:
cookieManager.setCookie("your url host", cookieString);
Pasé la mayor parte de las 3 horas trabajando en un problema muy similar. En mi caso tuve varias llamadas, que hice a un servicio web usando un DefaulHttpClient
y luego quise configurar la sesión y todas las demás cookies correspondientes en mi WebView
.
No sé si esto resolverá su problema, ya que no sé lo que hace su método getCookie()
, pero en mi caso tuve que llamar.
cookieManager.removeSessionCookie();
Primero, elimine la cookie de sesión y luego vuélvala a agregar. Estaba descubriendo que cuando traté de configurar la cookie JSESSIONID
sin eliminarla primero, el valor al que quería establecerlo no era guardar. No estoy seguro si esto lo ayudará con un problema en particular, pero pensé que compartiría lo que había encontrado.
Resolví mágicamente todos mis problemas de cookies con esta línea en onCreate:
CookieHandler.setDefault(new CookieManager());
editar: dejó de funcionar hoy. :( qué mierda, android.
Solución: Webview CookieSyncManager
CookieSyncManager cookieSyncManager = CookieSyncManager.createInstance(mWebView.getContext());
CookieManager cookieManager = CookieManager.getInstance();
cookieManager.setAcceptCookie(true);
cookieManager.removeSessionCookie();
cookieManager.setCookie("http://xx.example.com","mid="+MySession.GetSession().sessionId+" ; Domain=.example.com");
cookieSyncManager.sync();
String cookie = cookieManager.getCookie("http://xx.example.com");
Log.d(LOGTAG, "cookie ------>"+cookie);
mWebView.getSettings().setJavaScriptEnabled(true);
mWebView.setWebViewClient(new TuWebViewClient());
mWebView.loadUrl("http://xx.example.com");
Tengo un enfoque diferente de otras personas aquí, y es un enfoque que garantiza el trabajo sin tener que lidiar con el CookieSyncManager (donde está a merced de la semántica como "Tenga en cuenta que incluso la sincronización () ocurre de forma asíncrona").
Básicamente, buscamos el dominio correcto, luego ejecutamos javascript desde el contexto de la página para establecer cookies para ese dominio (de la misma manera que lo haría la página). Dos inconvenientes del método son que puede introducir un tiempo de ida y vuelta adicional debido a la solicitud HTTP adicional que debe realizar; y si su sitio no tiene el equivalente de una página en blanco, puede mostrar cualquier URL que cargue antes de llevarlo al lugar correcto.
import org.apache.commons.lang.StringEscapeUtils;
import org.apache.http.cookie.Cookie;
import android.annotation.SuppressLint;
import android.webkit.CookieManager;
import android.webkit.CookieSyncManager;
import android.webkit.WebView;
import android.webkit.WebViewClient;
public class WebViewFragment {
private static final String BLANK_PAGE = "/blank.html"
private CookieSyncManager mSyncManager;
private CookieManager mCookieManager;
private String mTargetUrl;
private boolean mInitializedCookies;
private List<Cookie> mAllCookies;
public WebViewFragment(Context ctx) {
// We are still required to create an instance of Cookie/SyncManager.
mSyncManager = CookieSyncManager.createInstance(ctx);
mCookieManager = CookieManager.getInstance();
}
@SuppressLint("SetJavaScriptEnabled") public void loadWebView(
String url, List<Cookie> cookies, String domain) {
final WebView webView = ...
webView.setWebViewClient(new CookeWebViewClient());
webView.getSettings().setJavaScriptEnabled(true);
mInitializedCookies = false;
mTargetUrl = url;
mAllCookies = cookies;
// This is where the hack starts.
// Instead of loading the url, we load a blank page.
webView.loadUrl("http://" + domain + BLANK_PAGE);
}
public static String buildCookieString(final Cookie cookie) {
// You may want to add the secure flag for https:
// + "; secure"
// In case you wish to convert session cookies to have an expiration:
// + "; expires=Thu, 01-Jan-2037 00:00:10 GMT"
// Note that you cannot set the HttpOnly flag as we are using
// javascript to set the cookies.
return cookie.getName() + "=" + cookie.getValue()
+ "; path=" + cookie.getPath()
+ "; domain=" + cookie.getDomain()
};
public synchronized String generateCookieJavascript() {
StringBuilder javascriptCode = new StringBuilder();
javascriptCode.append("javascript:(function(){");
for (final Cookie cookie : mAllCookies) {
String cookieString = buildCookieString(cookie);
javascriptCode.append("document.cookie=/"");
javascriptCode.append(
StringEscapeUtils.escapeJavascriptString(cookieString));
javascriptCode.append("/";");
}
// We use javascript to load the next url because we do not
// receive an onPageFinished event when this code finishes.
javascriptCode.append("document.location=/"");
javascriptCode.append(
StringEscapeUtils.escapeJavascriptString(mTargetUrl));
javascriptCode.append("/";})();");
return javascriptCode.toString();
}
private class CookieWebViewClient extends WebViewClient {
@Override public void onPageFinished(WebView view, String url) {
super.onPageFinished(view, url);
if (!mInitializedCookies) {
mInitializedCookies = true;
// Run our javascript code now that the temp page is loaded.
view.loadUrl(generateCookieJavascript());
return;
}
}
}
}
Si confía en el dominio de donde provienen las cookies, puede escapar sin apache commons, pero debe comprender que esto puede presentar un riesgo XSS si no tiene cuidado.
la solución es darle a Android suficiente tiempo para procesar las cookies. Puede encontrar más información aquí: http://code.walletapp.net/post/46414301269/passing-cookie-to-webview