Mam serwer, który wysyła do mojej aplikacji na Androida plik cookie sesji, który ma być używany do uwierzytelnionej komunikacji. Próbuję załadować WebView z adresem URL wskazującym na ten sam serwer i próbuję przekazać plik cookie sesji do uwierzytelnienia. Obserwuję, że działa sporadycznie, ale nie mam pojęcia dlaczego. Używam tego samego pliku cookie sesji, aby wykonywać inne wywołania na moim serwerze, a uwierzytelnianie nigdy nie kończy się niepowodzeniem. Obserwuję ten problem tylko podczas próby załadowania adresu URL w WebView i nie zdarza się to za każdym razem. Bardzo frustrujące.
Poniżej znajduje się kod, którego używam do tego. Każda pomoc będzie bardzo mile widziana.
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);
Odpowiedzi:
Dzięki justingrammens ! To zadziałało, udało mi się udostępnić plik cookie w ramach moich żądań DefaultHttpClient i aktywności 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(); }
źródło
Dzięki Androidowi za zrujnowanie mojej niedzieli. . . Oto, co naprawiło moje aplikacje (po uruchomieniu widoku internetowego)
if ( Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP ) { CookieManager cookieManager = CookieManager.getInstance(); cookieManager.setAcceptThirdPartyCookies( webView, true ); }
Powinienem powiedzieć, że powyższe odpowiedzi prawdopodobnie zadziałają, ale w mojej sytuacji w momencie, gdy Android przeszedł na wersję 5 +, moje `` aplikacje '' javascript webview na Androida umarły.
źródło
Rozwiązanie: 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");
źródło
cookie
?, dostaję tylko:PHPSESSID=ljfakdjfklasdfaj
!, czy to wystarczy?rozwiązaniem jest zapewnienie Androidowi wystarczająco dużo czasu na przetworzenie plików cookie. Więcej informacji można znaleźć tutaj: http://code.walletapp.net/post/46414301269/passing-cookie-to-webview
źródło
Zapisałbym ten sesyjny plik cookie jako preferencję i na siłę ponownie zapełniłbym nim menedżera plików cookie. Wygląda na to, że plik cookie sesji nie przetrwał ponownego uruchomienia działania
źródło
Większą połowę 3 godzin spędziłem nad bardzo podobnym problemem. W moim przypadku miałem kilka połączeń, które wykonałem z usługą internetową za pomocą a,
DefaulHttpClient
a następnie chciałem ustawić sesję i wszystkie inne odpowiednie pliki cookie w moimWebView
.Nie wiem, czy to rozwiąże twój problem, ponieważ nie wiem, co
getCookie()
robi twoja metoda, ale w moim przypadku faktycznie musiałem zadzwonić.cookieManager.removeSessionCookie();
Najpierw usuń plik cookie sesji, a następnie dodaj go ponownie. Odkryłem, że kiedy próbowałem ustawić
JSESSIONID
plik cookie bez uprzedniego usunięcia go, wartość, na którą chciałem go ustawić, nie była zapisywana. Nie jestem pewien, czy to pomoże ci w konkretnym problemie, ale pomyślałem, że podzielę się tym, co znalazłem.źródło
CookieManager.getInstance().removeAllCookie ();
?Po pewnym czasie poszukiwań zebrałem kilka elementów, które doprowadziły mnie do tego rozwiązania. Gdy CookieSyncManager zostanie przestarzały, może to być obecnie najlepszy sposób na ustawienie określonego pliku cookie dla widoku internetowego w Kotlin, nie powinieneś potrzebować niczego więcej.
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) }
źródło
Mam inne podejście niż inni ludzie tutaj i jest to podejście, które gwarantuje pracę bez zajmowania się CookieSyncManager (gdzie jesteś na łasce semantyki, takiej jak „Zauważ, że nawet sync () odbywa się asynchronicznie”).
Zasadniczo przechodzimy do właściwej domeny, a następnie wykonujemy javascript z kontekstu strony, aby ustawić pliki cookie dla tej domeny (tak samo jak sama strona). Dwie wady tej metody to to, że może to spowodować wydłużenie czasu podróży w obie strony ze względu na dodatkowe żądanie http, które musisz wykonać; a jeśli Twoja witryna nie ma odpowiednika pustej strony, może sflashować dowolny adres URL, który załadujesz jako pierwszy, zanim przeniesie Cię we właściwe miejsce.
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; } } } }
Jeśli ufasz domenie, z której pochodzą pliki cookie, możesz uciec bez apache commons, ale musisz zrozumieć, że może to stanowić ryzyko XSS, jeśli nie będziesz ostrożny.
źródło
To jest działający fragment kodu.
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(); } }
Tutaj httpclient jest obiektem DefaultHttpClient, który został użyty w żądaniu HttpGet / HttpPost. Należy również upewnić się, że należy podać nazwę i wartość pliku cookie
String cookieString = cookie.getName() + "=" + cookie.getValue();
setCookie ustawi plik cookie dla podanego adresu URL.
źródło
W magiczny sposób rozwiązałem wszystkie swoje problemy z plikami cookie za pomocą tej jednej linii w onCreate:
CookieHandler.setDefault(new CookieManager());
edycja: przestała działać dzisiaj. :( co do cholery, android.
źródło
To też spotkałem. Oto co zrobiłem.
Na moim LoginActivity, wewnątrz mojego AsyncTask, mam następujące elementy:
// WHERE CookieStoreHelper.sessionCookie to kolejna klasa zawierająca zmienną sessionCookie zdefiniowaną jako Lista plików cookie; a cookieStore definiuje się jako BasicCookieStore cookieStore;
Następnie na moim fragmencie, w którym znajduje się mój WebView, mam następujące elementy:
//DECLARE LIST OF COOKIE List<Cookie> sessionCookie;
wewnątrz mojej metody lub tuż przed ustawieniem 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 }
Szybka wskazówka: zainstaluj program firebug w przeglądarce Firefox lub użyj konsoli programisty w przeglądarce Chrome i najpierw przetestuj swoją stronę internetową, przechwyć plik cookie i sprawdź domenę, aby móc ją gdzieś przechowywać i upewnić się, że prawidłowo ustawiasz właściwą domenę.
Edycja: edytowano CookieStoreHelper.cookies do CookieStoreHelper.sessionCookie
źródło
Mój działający kod
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; }
Aby debugować zapytanie, „cookieManager.setCookie (....);” Polecam przejrzenie zawartości bazy danych webviewCookiesChromium.db (przechowywanej w "/data/data/my.app.webview/database"). Tam możesz zobaczyć prawidłowe ustawienia.
Wyłączenie "cookieManager.removeSessionCookie ();" i / lub „cookieManager.removeAllCookie ();”
//cookieManager.removeSessionCookie(); // and/or //cookieManager.removeAllCookie();"
Porównaj ustawione wartości z wartościami ustawionymi przez przeglądarkę. Dostosuj żądanie instalacji plików cookie, zanim "flagi" nie zostaną zainstalowane, przeglądarka będzie pasować do tego, co zdecydujesz. Zauważyłem, że zapytanie może być „flagami”:
// 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"
źródło
Kilka komentarzy (przynajmniej dla API> = 21), których dowiedziałem się z mojego doświadczenia i przyprawiło mnie o ból głowy:
http
ihttps
adresy URL są różne. Ustawienie pliku cookie dlahttp://www.example.com
różni się od ustawienia pliku cookie dlahttps://www.example.com
https://www.example.com/
działa, alehttps://www.example.com
nie działa.CookieManager.getInstance().setCookie
wykonuje operację asynchroniczną. Jeśli więc załadujesz adres URL zaraz po jego ustawieniu, nie ma gwarancji, że pliki cookie zostaną już zapisane. Aby zapobiec nieoczekiwanym i niestabilnym zachowaniom, użyj CookieManager # setCookie (String url, String value, ValueCallback callback) ( link ) i rozpocznij ładowanie adresu URL po wywołaniu wywołania zwrotnego.Mam nadzieję, że moje dwa grosze zaoszczędzą trochę czasu niektórym ludziom, więc nie będziesz musiał stawić czoła tym samym problemom, co ja.
źródło
Napotkałem ten sam problem i rozwiąże ten problem we wszystkich wersjach Androida
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); } }
źródło
Zauważ, że może lepiej jest użyć subdomen zamiast zwykłego adresu URL. Więc
.example.com
zamiasthttps://example.com/
.Dzięki Jody Jacobus Geers i innym napisałem tak:
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) }
źródło
Nie używaj surowego adresu URL
Zamiast:
cookieManager.setCookie(myUrl, cookieString);
użyj tego w ten sposób:
cookieManager.setCookie("your url host", cookieString);
źródło