Подтвердить что ты не робот

Передача файлов cookie из HttpURLConnection (java.net.CookieManager) в WebView (android.webkit.CookieManager)

Я видел ответы о том, как это должно работать со старым DefaultHttpClientно нет хорошего примера для HttpURLConnection

Я использую HttpURLConnection, чтобы делать запросы к веб-приложению. В начале моего приложения для Android я использую CookieHandler.setDefault(new CookieManager()), чтобы автоматически обрабатывать файлы cookie сеанса, и это работает нормально.

В какой-то момент после входа в систему я хочу показывать в реальном времени страницы из веб-приложения пользователю WebView вместо загрузки данных за кулисами с помощью HttpURLConnection. Тем не менее, я хочу использовать тот же самый сеанс, который я установил ранее, чтобы не допустить повторного входа пользователя.

Как скопировать файлы cookie из java.net.CookieManager, используемые HttpURLConnection в android.webkit.CookieManager, используемые WebView, чтобы я мог поделиться сеансом?

4b9b3361

Ответ 1

По сравнению с DefaultHttpClient, есть несколько дополнительных шагов. Ключевым отличием является доступ к существующим файлам cookie в HTTPURLConnection:

  • Вызвать CookieHandler.getDefault() и передать результат в java.net.CookieManager.
  • В менеджере файлов cookie вызовите getCookieStore() для доступа к хранилищу файлов cookie.
  • В хранилище файлов cookie вызовите get(), чтобы получить доступ к списку файлов cookie для данного URI.

Вот полный пример:

@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
    ...
}

Ответ 2

Я хотел бы предложить совершенно другой подход к вашей проблеме. Вместо копирования файлов cookie из одного места в другое (ручная синхронизация), пусть HttpURLConnection и WebViews используют хранилище cookie ..

Это полностью исключает необходимость синхронизации. Любой cookie, обновленный в любом из них, будет немедленно и автоматически отражен в другом.

Для этого создайте свою собственную реализацию java.net.CookieManager, которая пересылает все запросы веб-браузеру webkit android.webkit.CookieManager.

Реализация:

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

и, наконец, использовать его, выполнив это при инициализации вашего приложения:

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

Ответ 3

Я волшебно решил все свои проблемы с файлом cookie с этой одной строкой в ​​onCreate:

CookieHandler.setDefault(new CookieManager());

Ответ 4

У меня была та же проблема, и это мое решение:

Сразу после входа в систему (это важно, потому что раньше у вас может быть еще не cookie), используя httpurlconnection POST (после getResponseCode), я:

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

(где cookie - это публичная строка в моем классе)

И в активности веб-просмотра, где я хочу отображать веб-страницу с сервера с помощью WebView, я делаю:

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

Поскольку мой веб-просмотр в фрагменте, мне пришлось использовать getActivity() для контекста, мне также пришлось указать android.webkit. перед CookieManager иначе он не может быть разрешен (импортируйте java.net вместо менеджера android.webkit cookie).

cookie - это та же строка, что и выше (в моем фрагменте мне пришлось восстановить его, используя:

    cookie = getArguments().getString(COOKIE);

и в моей MainActivity, я отправляю его по:

    Bundle arg = new Bundle();
    arg.putString(Fragment_Cameras.COOKIE, cookie);
    fragment.setArguments(arg);

Я надеюсь, это поможет!