webentwicklung-frage-antwort-db.com.de

Android WebView-Cookie-Problem

Ich habe einen Server, der meiner Android-App ein Sitzungs-Cookie sendet, das für die __. authentifizierte Kommunikation verwendet werden soll. Ich versuche, ein WebView mit einer URL Zu laden, die auf denselben Server verweist, und ich versuche, die Session -Cookie zur Authentifizierung zu übergeben. Ich beobachte, dass es zeitweise funktioniert, aber ich habe keine Ahnung, warum. Ich benutze das gleiche Session-Cookie, um andere Anrufe auf meinem Server zu tätigen, und diese Authentifizierung schlägt niemals fehl. Dieses Problem tritt nur bei dem Versuch auf, eine URL in eine WebView zu laden, und es tritt nicht jedes Mal auf. Sehr frustrierend.

Unten ist der Code, den ich dazu benutze. Jede Hilfe wird sehr geschätzt. 

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);
78
nannerpus

Danke justingrammens ! Das hat für mich funktioniert, es ist mir gelungen, das Cookie in meinen DefaultHttpClient-Anforderungen und meiner WebView-Aktivität zu teilen:

//------- 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();
}   
51
k7k0

Lösung: 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");
14
Sanket

Danke, Android, dass ich meinen Sonntag ruiniert habe. . . Heres, was meine Apps behoben hat (nachdem Sie Ihren Webview gestartet haben)

if ( Build.VERSION.SDK_INT >= Build.VERSION_CODES.Lollipop ) {

  CookieManager cookieManager = CookieManager.getInstance();

  cookieManager.setAcceptThirdPartyCookies( webView, true );

}

Ich sollte sagen, dass die obigen Antworten wahrscheinlich funktionieren werden, aber in meiner Situation starb Android v5 + mein Android-Webview-Javascript "Apps".

9

die Lösung ist, dem Android genügend Zeit für die Verarbeitung von Cookies zu geben. Weitere Informationen finden Sie hier: http://code.walletapp.net/post/46414301269/passing-cookie-to-webview

8
Jan Muller

Ich würde dieses Session-Cookie als Präferenz speichern und den Cookie-Manager zwangsweise damit auffüllen. Es scheint, dass das Session-Cookie den Neustart der Aktivität nicht überlebt

3
Bostone

Ich habe die Hälfte von 3 Stunden damit verbracht, an einem sehr ähnlichen Thema zu arbeiten. In meinem Fall hatte ich eine Reihe von Anrufen, die ich mit einem DefaulHttpClient an einen Webdienst gerichtet hatte, und dann wollte ich die Sitzung und alle anderen entsprechenden Cookies in meinem WebView einstellen.

Ich weiß nicht, ob dies Ihr Problem lösen wird, da ich nicht weiß, was Ihre getCookie() -Methode tut, aber in meinem Fall musste ich tatsächlich aufrufen.

cookieManager.removeSessionCookie();

Entfernen Sie zuerst das Sitzungscookie und fügen Sie es dann erneut hinzu. Als ich versuchte, das Cookie JSESSIONID zu setzen, ohne es zuvor zu entfernen, stellte ich fest, dass der Wert, auf den ich es setzen wollte, nicht gespeichert wurde. Ich bin mir nicht sicher, ob dies Ihnen bei einem bestimmten Problem helfen wird, dachte aber, ich würde mitteilen, was ich gefunden habe.

3
Justin

Dies traf auch auf. Hier ist was ich getan habe.

Auf meiner LoginActivity, in meiner AsyncTask, habe ich Folgendes:

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 ist eine andere Klasse, die die Variable listCookie enthält, die als List-Cookies definiert ist. und cookieStore als BasicCookieStore cookieStore definieren;

Dann habe ich auf meinem Fragment, wo sich meine WebView befindet, folgendes:

//DECLARE LIST OF COOKIE
List<Cookie> sessionCookie;

in meiner Methode oder kurz bevor Sie den WebViewClient () einstellen

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
 }

Kurztipp: Lassen Sie firebug auf firefox installieren oder verwenden Sie die Entwicklerkonsole auf chrome und testen Sie zunächst Ihre Webseite, nehmen Sie den Cookie auf und überprüfen Sie die Domäne, sodass Sie sie irgendwo speichern können und sicherstellen, dass Sie die richtige Domäne richtig einstellen.

Bearbeiten: CookieStoreHelper.cookies wurde in CookieStoreHelper.sessionCookie bearbeitet

1
Burnok

Ich habe hier eine andere Herangehensweise als andere Leute, und es ist eine Vorgehensweise, die garantiert funktioniert, ohne sich mit dem CookieSyncManager zu befassen (wo Sie der Semantik ausgeliefert sind, wie "Beachten Sie, dass sogar sync () asynchron geschieht).

Im Wesentlichen navigieren wir zur korrekten Domain und führen dann Javascript aus dem Seitenkontext aus, um Cookies für diese Domain zu setzen (genauso wie die Seite selbst). Zwei Nachteile der Methode sind, dass aufgrund der zusätzlichen HTTP-Anforderung, die Sie stellen müssen, eine zusätzliche Umlaufzeit entstehen kann. Wenn Ihre Website nicht das Äquivalent einer leeren Seite hat, kann sie die URL, die Sie zuerst laden, blinken lassen, bevor Sie an den richtigen Ort gelangen.

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;
            }
        }
    }
}

Wenn Sie der Domäne, von der die Cookies stammen, vertrauen, können Sie möglicherweise ohne Apache-Commons davonkommen. Sie müssen jedoch verstehen, dass dies ein XSS-Risiko darstellen kann, wenn Sie nicht vorsichtig sind.

1
Patrick Horn

Ich habe auf magische Weise alle meine Cookie-Probleme mit dieser einen Zeile in onCreate gelöst:

CookieHandler.setDefault(new CookieManager());

edit: es hat heute aufgehört zu funktionieren. :( was zum Teufel, Android.

1
Chani

Mein Arbeitscode

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;
}

Um die Abfrage zu debuggen, "cookieManager.setCookie (....);" Ich empfehle Ihnen, den Inhalt der Datenbank webviewCookiesChromium.db (gespeichert in "/data/data/my.app.webview/database") durchzusehen. Dort können Sie die richtigen Einstellungen sehen.

Deaktivierung von "cookieManager.removeSessionCookie ();" und/oder "cookieManager.removeAllCookie ();"

//cookieManager.removeSessionCookie();
// and/or
//cookieManager.removeAllCookie();"

Vergleichen Sie den eingestellten Wert mit den vom Browser festgelegten Werten. Passen Sie die Anforderung für die Installation der Cookies an, bis der Browser "flags" nicht installiert ist und zu Ihrer Entscheidung passt. Ich habe festgestellt, dass eine Abfrage "Flags" sein kann:

// 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"
1
Vadim.Ivanov

Dies ist ein funktionierender Code. 

    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();
    }
}

Der httpclient ist hier das DefaultHttpClient-Objekt, das Sie in der Anforderung HttpGet/HttpPost verwendet haben. Um sicherzugehen, dass auch der Name und der Wert des Cookies angegeben werden, sollte dieser angegeben werden

String cookieString = cookie.getName() + "=" + cookie.getValue();

setCookie setzt das Cookie für die angegebene URL.

1
droid kid

Einige Kommentare (zumindest für APIs> = 21), die ich aus meiner Erfahrung herausgefunden habe und mir Kopfschmerzen bereitete:

  1. http- und https-URLs sind unterschiedlich. Das Setzen eines Cookies für http://www.example.com unterscheidet sich vom Setzen eines Cookies für https://www.example.com.
  2. Ein Schrägstrich am Ende der URL kann ebenfalls einen Unterschied machen. In meinem Fall funktioniert https://www.example.com/, aber https://www.example.com funktioniert nicht.
  3. CookieManager.getInstance().setCookie führt eine asynchrone Operation aus. Wenn Sie also eine URL direkt nach dem Festlegen laden, kann nicht garantiert werden, dass die Cookies bereits geschrieben wurden. Um unerwartetes und instabiles Verhalten zu vermeiden, verwenden Sie den CookieManager # setCookie (String url, String value, ValueCallback callback) ( link ) und starten Sie das Laden der URL, nachdem der Callback aufgerufen wird.

Ich hoffe, dass meine zwei Cents von einigen Leuten etwas Zeit sparen, so dass Sie nicht mit den gleichen Problemen konfrontiert werden müssen wie ich.

0
giorgos29cm

Ich bin mit demselben Problem konfrontiert und es wird dieses Problem in allen Android-Versionen beheben

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);
    }
}
0
Prinkal Kumar