Tengo un servidor que envía a mi aplicación de Android una cookie de sesión que se utilizará para la comunicación autenticada. Estoy intentando cargar un WebView con una URL que apunta a ese mismo servidor y estoy intentando pasar la cookie de sesión para la autenticación. Observo que funciona de forma intermitente, 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 en la autenticación. Solo observo este problema cuando intento cargar una URL en un WebView, y no sucede siempre. Muy frustrante.
A continuación se muestra 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);
Respuestas:
¡Gracias justingrammens ! Eso funcionó para mí, logré compartir la cookie dentro de mis solicitudes DefaultHttpClient y actividad 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(); }
fuente
Gracias Android por arruinarme el domingo. . . Esto es lo que solucionó mis aplicaciones (después de iniciar su vista 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 funcionarán, pero en mi situación, en el momento en que Android se convirtió en v5 +, mis 'aplicaciones' javascript de Android Webview murieron.
fuente
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");
fuente
cookie
?, solo me sale como:PHPSESSID=ljfakdjfklasdfaj
!, ¿es eso suficiente?la solución es darle a Android el tiempo suficiente para procesar las cookies. Puede encontrar más información aquí: http://code.walletapp.net/post/46414301269/passing-cookie-to-webview
fuente
Guardaría esa cookie de sesión como una preferencia y volvería a llenar con fuerza el administrador de cookies con ella. Suena que la cookie de sesión no sobrevive al reinicio de la actividad
fuente
Pasé la mayor parte de las 3 horas trabajando en un problema muy similar. En mi caso, tuve una serie de llamadas, que hice a un servicio web usando un
DefaulHttpClient
y luego quería configurar la sesión y todas las demás cookies correspondientes en miWebView
.No sé si esto resolverá tu problema, ya que no sé qué hace tu
getCookie()
método, pero en mi caso tuve que llamar.cookieManager.removeSessionCookie();
Primero para eliminar la cookie de sesión y luego volver a agregarla. Descubrí que cuando intenté configurar la
JSESSIONID
cookie sin eliminarla primero, el valor que quería configurar no se estaba guardando. No estoy seguro de si esto le ayudará en un problema en particular, pero pensé en compartir lo que había encontrado.fuente
CookieManager.getInstance().removeAllCookie ();
?Después de un tiempo investigando, reuní algunas piezas que me hicieron llegar a esta solución. Una vez que CookieSyncManager esté obsoleto, esta puede ser la mejor manera de configurar una cookie específica para una vista web en Kotlin hoy en día, no debería necesitar nada más.
private fun setCookie(){ val webView = WebView(this) // this = context val cookieManager = CookieManager.getInstance() cookieManager.acceptCookie() val domain = "https://www.yourdomain.com/" webView.webViewClient = WebViewClient() webView.settings.javaScriptEnabled = true cookieManager.setCookie(domain,"$cookieKey=$cookieValue") cookieManager.setAcceptThirdPartyCookies(webView, true) webView.loadUrl(domain) }
fuente
Tengo un enfoque diferente al de otras personas aquí, y es un enfoque que garantiza el trabajo sin tener que lidiar con CookieSyncManager (donde estás a merced de semánticas como "Tenga en cuenta que incluso sync () ocurre de forma asincrónica").
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 a una página en blanco, puede mostrar la URL que cargue primero 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 del que provienen las cookies, es posible que pueda escapar sin apache commons, pero debe comprender que esto puede presentar un riesgo XSS si no tiene cuidado.
fuente
Este es un fragmento 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í, httpclient es el objeto DefaultHttpClient que usó en la solicitud HttpGet / HttpPost. También una cosa que debe asegurarse es el nombre y el valor de la cookie, debe proporcionarse
String cookieString = cookie.getName() + "=" + cookie.getValue();
setCookie establecerá la cookie para la URL dada.
fuente
Resolví mágicamente todos mis problemas con las cookies con esta línea en onCreate:
CookieHandler.setDefault(new CookieManager());
editar: dejó de funcionar hoy. :( que mierda, android.
fuente
También encontré esto. Esto es lo que hice.
En mi LoginActivity, dentro de mi AsyncTask, tengo lo siguiente:
// DONDE CookieStoreHelper.sessionCookie es otra clase que contiene la variable sessionCookie definida como List cookies; y cookieStore se definen 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 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 la cookie y verifique el dominio para que pueda almacenarlo en algún lugar y asegúrese de que está configurando correctamente el dominio correcto.
Editar: CookieStoreHelper.cookies editado a CookieStoreHelper.sessionCookie
fuente
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 (almacenada 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 establecidos por el navegador. Ajustar la solicitud de instalación de las cookies antes de que no se instalen "banderas" del navegador se ajustará a lo que Usted decida. Descubrí 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"
fuente
Un par de comentarios (al menos para API> = 21) que descubrí por mi experiencia y me dieron dolores de cabeza:
http
y lashttps
URL son diferentes. Configurar una cookie parahttp://www.example.com
es diferente a configurar una cookie parahttps://www.example.com
https://www.example.com/
funciona perohttps://www.example.com
no funciona.CookieManager.getInstance().setCookie
está realizando una operación asincrónica. Por lo tanto, si carga una URL inmediatamente después de configurarla, no se garantiza que las cookies ya se hayan escrito. Para evitar comportamientos inesperados e inestables, use CookieManager # setCookie (URL de cadena, valor de cadena, devolución de llamada de ValueCallback) ( enlace ) y comience a cargar la URL después de que se llame a la devolución de llamada.Espero que mis dos centavos le ahorren algo de tiempo a algunas personas para que no tenga que enfrentar los mismos problemas que yo.
fuente
Me he enfrentado al mismo problema y resolverá este problema en todas las versiones de Android
private void setCookie() { try { CookieSyncManager.createInstance(context); CookieManager cookieManager = CookieManager.getInstance(); cookieManager.setAcceptCookie(true); if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) { cookieManager.setCookie(Constant.BASE_URL, getCookie(), value -> { String cookie = cookieManager.getCookie(Constant.BASE_URL); CookieManager.getInstance().flush(); CustomLog.d("cookie", "cookie ------>" + cookie); setupWebView(); }); } else { cookieManager.setCookie(webUrl, getCookie()); new Handler().postDelayed(this::setupWebView, 700); CookieSyncManager.getInstance().sync(); } } catch (Exception e) { CustomLog.e(e); } }
fuente
Tenga en cuenta que puede ser mejor utilizar subdominios en lugar de la URL habitual. Entonces, establezca en
.example.com
lugar dehttps://example.com/
.Gracias a Jody Jacobus Geers y otros escribí así:
if (savedInstanceState == null) { val cookieManager = CookieManager.getInstance() cookieManager.acceptCookie() val domain = ".example.com" if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) { cookieManager.setCookie(domain, "token=$token") { view.webView.loadUrl(url) } cookieManager.setAcceptThirdPartyCookies(view.webView, true) } else { cookieManager.setCookie(domain, "token=$token") view.webView.loadUrl(url) } } else { // Check whether we're recreating a previously destroyed instance. view.webView.restoreState(savedInstanceState) }
fuente
No uses tu URL sin procesar
En vez de:
cookieManager.setCookie(myUrl, cookieString);
úsalo así:
cookieManager.setCookie("your url host", cookieString);
fuente