Przekazywanie plików cookie z HttpURLConnection (java. net. CookieManager) do WebView (android.webkit.CookieManager)

widziałem odpowiedzi Jak to powinno działać ze starym DefaultHttpClient ale nie ma dobrego przykładu dla HttpURLConnection

Używam HttpURLConnection do wysyłania zapytań do aplikacji internetowej. Na początku aplikacji Mój Android używam CookieHandler.setDefault(new CookieManager()), aby automatycznie radzić sobie z plikami cookie sesji, i to działa dobrze.

W pewnym momencie po zalogowaniu chcę pokazać użytkownikowi aktywne strony z aplikacji internetowej za pomocą WebView pobierania danych zza kulis za pomocą HttpURLConnection. Chcę jednak użyć tej samej sesji, którą ustanowiłem wcześniej, aby zapobiec ponownemu zalogowaniu się użytkownika.

Jak skopiować pliki cookie z java.net.CookieManager używane przez HttpURLConnection do android.webkit.CookieManager używane przez WebView, Aby móc udostępnić sesję?

Author: quietmint, 2012-10-04

4 answers

Chciałbym zaproponować zupełnie inne podejście do twojego problemu. Zamiast kopiowania plików cookie z jednego miejsca do drugiego (ręczna synchronizacja), Sprawmy, aby HttpURLConnection i Webview korzystały z tego samego przechowywania plików cookie.

To całkowicie eliminuje potrzebę synchronizacji. Każdy plik cookie zaktualizowany w jednym z nich, zostanie natychmiast i automatycznie odzwierciedlony w drugim.

Aby to zrobić, Stwórz własną implementację java. net. CookieManager, która przekazuje wszystkie żądania do WebViews ' webkit android.webkit.CookieManager.

Realizacja:

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

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

I na koniec użyj go, wykonując to przy inicjalizacji aplikacji:

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);
 55
Author: talkol,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2013-08-06 02:09:11

W porównaniu z DefaultHttpClient, Istnieje kilka dodatkowych kroków. Kluczowa różnica polega na tym, jak uzyskać dostęp do istniejących plików cookie w HTTPURLConnection:

  1. wywołaj CookieHandler.getDefault() i prześlij wynik do java.net.CookieManager.
  2. z menedżerem plików cookie, zadzwoń getCookieStore(), aby uzyskać dostęp do sklepu z plikami cookie.
  3. za pomocą pliku cookie Store, zadzwoń get(), aby uzyskać dostęp do listy plików cookie dla danego URI.

Oto kompletny przykład:

@Override
protected void onCreate(Bundle savedInstanceState) {
    // Get cookie manager for WebView
    // This must occur before setContentView() instantiates your WebView
    android.webkit.CookieSyncManager webCookieSync =
        CookieSyncManager.createInstance(this);
    android.webkit.CookieManager webCookieManager =
        CookieManager.getInstance();
    webCookieManager.setAcceptCookie(true);

    // Get cookie manager for HttpURLConnection
    java.net.CookieStore rawCookieStore = ((java.net.CookieManager)
        CookieHandler.getDefault()).getCookieStore();

    // Construct URI
    java.net.URI baseUri = null;
    try {
        baseUri = new URI("http://www.example.com");
    } catch (URISyntaxException e) {
        // Handle invalid URI
        ...
    }

    // Copy cookies from HttpURLConnection to WebView
    List<HttpCookie> cookies = rawCookieStore.get(baseUri);
    String url = baseUri.toString();
    for (HttpCookie cookie : cookies) {
        String setCookie = new StringBuilder(cookie.toString())
            .append("; domain=").append(cookie.getDomain())
            .append("; path=").append(cookie.getPath())
            .toString();
        webCookieManager.setCookie(url, setCookie);
    }

    // Continue with onCreate
    ...
}
 18
Author: quietmint,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2012-10-04 16:00:24

Magicznie rozwiązałem wszystkie moje problemy z ciasteczkami z tą jedną linijką w onCreate:

CookieHandler.setDefault(new CookieManager());

 11
Author: Chani,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2013-10-18 00:15:09

Miałem ten sam problem, a to jest moje rozwiązanie:

Tuż po zalogowaniu (ważne, bo wcześniej możesz nie mieć jeszcze cookie) używając HTTPURLCONNECTION POST( po getResponseCode), robię :

 responseCode = connexion.getResponseCode();
 if (responseCode == HttpURLConnection.HTTP_OK) {
     final String COOKIES_HEADER = "Set-Cookie";
     cookie = connexion.getHeaderField(COOKIES_HEADER);
     ...
 }

(gdzie cookie jest publicznym ciągiem w mojej klasie)

I w aktywności webview, gdzie chcę wyświetlić stronę internetową z serwera za pomocą WebView, robię:

    String url = "http://toto.com/titi.html";        // the url of the page you want to display
    CookieSyncManager.createInstance(getActivity());
    CookieSyncManager.getInstance().startSync();
    android.webkit.CookieManager cookieManager = android.webkit.CookieManager.getInstance();
    cookieManager.setAcceptCookie(true);
    cookieManager.removeSessionCookie();
    cookieManager.setCookie(url, cookie);
    CookieSyncManager.getInstance().sync();

Ponieważ mój webview jest we fragmencie, musiałem użyć getActivity () dla kontekstu, musiałem też określ system android.webkit. przed CookieManager inaczej nie może być rozwiązany (import java.net zamiast Androida.webkit cookie manager).

Cookie to ten sam ciąg znaków jak powyżej (w moim fragmencie musiałem go odzyskać używając :

    cookie = getArguments().getString(COOKIE);

I w głównej mierze wysyłam przez:

    Bundle arg = new Bundle();
    arg.putString(Fragment_Cameras.COOKIE, cookie);
    fragment.setArguments(arg);
To może pomóc !
 -2
Author: Christian,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2014-11-28 09:14:24