如何使用OkHttp在Android上实现cookie处理?

问题描述 投票:0回答:4

使用 Square 的 OkHttp https://github.com/square/okhttp,我该怎么做:

  1. 检索从服务器返回的cookie
  2. 为即将到来的请求存储 cookie
  3. 在后续请求中使用存储的cookie
  4. 更新后续请求返回的cookie

理想情况下,每次请求时都会自动存储、重新发送和更新 cookie。

android cookies okhttp
4个回答
75
投票

对于 OkHttp3,一个简单的接受所有、非持久的

CookieJar
实现可以如下:

OkHttpClient client = new OkHttpClient.Builder()
    .cookieJar(new CookieJar() {
        private final HashMap<HttpUrl, List<Cookie>> cookieStore = new HashMap<>();

        @Override
        public void saveFromResponse(HttpUrl url, List<Cookie> cookies) {
            cookieStore.put(url, cookies);
        }

        @Override
        public List<Cookie> loadForRequest(HttpUrl url) {
            List<Cookie> cookies = cookieStore.get(url);
            return cookies != null ? cookies : new ArrayList<Cookie>();
        }
    })
    .build();

或者,如果您更喜欢使用

java.net.CookieManager
,请在您的项目中包含
okhttp-urlconnection
,其中包含
JavaNetCookieJar
,一个委托给
java.net.CookieHandler
的包装类:

dependencies {
    compile "com.squareup.okhttp3:okhttp:3.0.0"
    compile "com.squareup.okhttp3:okhttp-urlconnection:3.0.0"
}

CookieManager cookieManager = new CookieManager();
cookieManager.setCookiePolicy(CookiePolicy.ACCEPT_ALL);
OkHttpClient client = new OkHttpClient.Builder()
    .cookieJar(new JavaNetCookieJar(cookieManager))
    .build();

36
投票

对于 OkHttp 3 (或者可能更新)

参见hidro的回答

对于 OkHttp 2.x (或者可能更旧)

您可以将 CookieHandler 传递给您的 OkHttpClient 实例。您可以使用 java.net 中的 CookieManager 实现,或者如果您愿意,也可以实现您自己的。选择最适合您需求的政策。

OkHttpClient client = new OkHttpClient();
CookieManager cookieManager = new CookieManager();
cookieManager.setCookiePolicy(CookiePolicy.ACCEPT_ALL);
client.setCookieHandler(cookieManager);

OkHttp将从Responses接收到的cookie保存到CookieHandler中,并在发送请求时从中读取。它将这样做以匹配请求/响应 URI。


9
投票

我需要共享默认的 Cookie Jar (CookieManager.getInstance()),所以这对我来说似乎没问题。

return new CookieJar() {

        @Override
        public void saveFromResponse(HttpUrl url, List<Cookie> cookies) {
            CookieManager cookieManager = CookieManager.getInstance();

            for (Cookie cookie : cookies) {
                cookieManager.setCookie(url.toString(), cookie.toString());
            }
        }

        @Override
        public List<Cookie> loadForRequest(HttpUrl url) {
            CookieManager cookieManager = CookieManager.getInstance();
            List<Cookie> cookies = new ArrayList<>();
            if (cookieManager.getCookie(url.toString()) != null) {
                String[] splitCookies = cookieManager.getCookie(url.toString()).split("[,;]");
                for (int i=0; i<splitCookies.length; i++) {
                    cookies.add(Cookie.parse(url, splitCookies[i].trim()));
                }
            }
            return cookies;
        }
    };

0
投票

这里我如何实现 android 棒棒糖 - 提拉米苏以及 jvm 和非持久连接的 cookie 处理。

import android.content.Context
import android.webkit.WebView
import okhttp3.Cookie
import okhttp3.CookieJar
import okhttp3.HttpUrl
import java.net.CookieHandler
import java.net.CookiePolicy
import java.net.HttpCookie


/**
 * android webkit webview cookie manager.
 * [FULL USAGES](https://dimaslanjaka.github.io/2024/03/okhttp-cookie-handling-on-android.html)
 *
 * @author Dimas Lanjaka <a href="https://www.webmanajemen.com">https://www.webmanajemen.com</a>
 */
open class WebkitCookieManager : CookieJar {
    /**
     * support for below android 10
     */
    private var webkitCookieManager: android.webkit.CookieManager? = null

    /**
     * support for jvm or android 10+
     */
    private var javaCookieManager: java.net.CookieManager? = null

    /**
     * support for webview intercept connection cookie handling
     */
    private var webview: WebView? = null

    /**
     * the android context for clearing cookies on non-webview instance
     */
    private var context: Context? = null

    /**
     * for non-persistent cookies
     */
    private val cookieStore = mutableMapOf<HttpUrl, List<Cookie>>()

    /**
     * construct android cookie manager without webview
     */
    constructor(manager: android.webkit.CookieManager, ctx: Context? = null) {
        webkitCookieManager = manager
        setupAndroidCookieManager()
        this.context = ctx
    }

    /**
     * construct android cookie manager with webview
     */
    constructor(manager: android.webkit.CookieManager, webView: WebView, ctx: Context? = null) {
        webkitCookieManager = manager
        setupAndroidCookieManager(webView)
        this.webview = webView
        this.context = ctx
    }

    /**
     * construct non-persistent cookie manager
     */
    constructor(ctx: Context? = null) {
        this.context = ctx
    }

    /**
     * construct java cookie manager
     */
    constructor(manager: java.net.CookieManager, ctx: Context? = null) {
        manager.setCookiePolicy(CookiePolicy.ACCEPT_ALL)
        javaCookieManager = manager
        CookieHandler.setDefault(javaCookieManager)
        this.context = ctx
    }

    /**
     * make android webkit cookie manager accept third-party cookies
     */
    private fun setupAndroidCookieManager(webView: WebView? = null) {
        webkitCookieManager?.setAcceptCookie(true);
        if (webView != null) webkitCookieManager?.setAcceptThirdPartyCookies(webView, true);
    }

    /**
     * save cookies after request finished
     */
    override fun saveFromResponse(url: HttpUrl, cookies: List<Cookie>) {
        cookies.forEach { cookie ->
            webkitCookieManager?.setCookie(url.toString(), cookie.toString())
            javaCookieManager?.cookieStore?.add(url.toUri(), HttpCookie.parse(cookie.toString())[0])
        }
        cookieStore.put(url, cookies);
    }

    /**
     * load cookies before okhttp execute request {@link okhttp3.OkHttpClient#newCall(request)}
     */
    override fun loadForRequest(url: HttpUrl): List<Cookie> {
        return if (webkitCookieManager != null) {
            // get from android webkit cookie manager
            when (val cookies = webkitCookieManager?.getCookie(url.toString())) {
                null -> emptyList()
                else -> cookies.split("; ").mapNotNull { Cookie.parse(url, it) }
            }
        } else if (javaCookieManager != null) {
            // get from java cookie manager
            when (val cookies = javaCookieManager?.cookieStore?.cookies) {
                null -> emptyList()
                else -> cookies.toString().split("; ").mapNotNull { Cookie.parse(url, it) }
            }
        } else {
            // get from non-persisten cookie store
            val cookies = cookieStore[url]
            return cookies ?: ArrayList()
        }
    }

    /**
     * clear all stored cookies everywhere
     */
    fun clearCookies() {
        // remove non-persistent stored cookies
        cookieStore.clear()
        // initialize android webkit cookie manager on null
        if (webkitCookieManager == null) {
            webkitCookieManager = android.webkit.CookieManager.getInstance()
            setupAndroidCookieManager()
        }
        // indicator when webview not initialized
        var standaloneWebview = false
        // initalize fake webview instance
        if (webview == null && context != null) {
            // declare standalone webview
            webview = WebView(context!!)
            // treat as standalone webview
            standaloneWebview = true
        }
        // remove all stored cookies from android webkit cookie manager
        webkitCookieManager?.removeAllCookies(null)
        webkitCookieManager?.flush()
        webkitCookieManager?.removeSessionCookies(null);
        // clear all caches from webview
        webview?.clearCache(true)
        webview?.clearHistory()
        webview?.clearFormData();
        webview?.clearSslPreferences();
        if (standaloneWebview) {
            // destroy standalone webview
            webview?.destroy()
            webview = null
        }
        // initialize java cookie manager
        if (javaCookieManager == null) {
            javaCookieManager = java.net.CookieManager(null, CookiePolicy.ACCEPT_ALL)
            java.net.CookieHandler.setDefault(javaCookieManager)
        }
        // remove all stored cookies from java cookie manager
        javaCookieManager?.cookieStore?.removeAll()
    }
}

我在视图绑定 webview + 自定义 webviewclient 中使用 okhttp 进行拦截

val clientBuilder = OkHttpClient.Builder()
clientBuilder.cookieJar(WebkitCookieManager(CookieManager.getInstance(), binding!!webview, applicationContext))

这项工作并经过测试,当我清除 cookie 时,网站上 cookie 的值发生了变化,否则在 cookie 过期之前都保持不变。

© www.soinside.com 2019 - 2024. All rights reserved.