You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Kotlin Jetpack Compose中Apollo Client存储会话Cookie问题求助

Kotlin Apollo Client 无法存储会话Cookie的解决建议

核心原因

Kotlin 中使用的 OkHttpClient 默认不会自动持久化 Cookie,而 Web/iOS 的原生 HTTP 客户端默认带有 Cookie 存储机制,这是导致差异的关键。

解决方案步骤

1. 实现持久化 CookieJar

创建一个基于 SharedPreferences 的 Cookie 存储类,用于保存和加载 Cookie:

import android.content.Context
import android.content.SharedPreferences
import okhttp3.Cookie
import okhttp3.CookieJar
import okhttp3.HttpUrl
import java.util.*
import kotlin.collections.HashMap

class PersistentCookieStore(context: Context) : CookieJar {
    private val prefs: SharedPreferences = context.getSharedPreferences("CookiePrefs", Context.MODE_PRIVATE)
    private val cookies: MutableMap<String, MutableList<Cookie>> by lazy {
        loadCookies()
    }

    private fun loadCookies(): MutableMap<String, MutableList<Cookie>> {
        val cookieMap = HashMap<String, MutableList<Cookie>>()
        val savedCookieStrings = prefs.getStringSet("cookies", emptySet()) ?: emptySet()
        
        savedCookieStrings.forEach { cookieStr ->
            Cookie.parse(HttpUrl.get("http://10.0.2.2:4000"), cookieStr)?.let { cookie ->
                val domain = cookie.domain()
                cookieMap.getOrPut(domain) { mutableListOf() }.add(cookie)
            }
        }
        return cookieMap
    }

    private fun saveCookies() {
        val cookieStrings = HashSet<String>()
        cookies.values.flatten().forEach { cookie ->
            cookieStrings.add(cookie.toString())
        }
        prefs.edit().putStringSet("cookies", cookieStrings).apply()
    }

    override fun saveFromResponse(url: HttpUrl, cookies: List<Cookie>) {
        val domain = url.host()
        cookies.forEach { cookie ->
            cookies.getOrPut(domain) { mutableListOf() }.add(cookie)
        }
        saveCookies()
    }

    override fun loadForRequest(url: HttpUrl): List<Cookie> {
        return cookies.getOrDefault(url.host(), emptyList())
    }
}

2. 配置 OkHttpClient 并关联 Apollo Client

修改你的 Apollo Client 构建代码,将自定义的 CookieJar 注入到 OkHttpClient:

// 传入 Context 实例(如 Activity/Fragment 的 context)
val okHttpClient = OkHttpClient.Builder()
    .cookieJar(PersistentCookieStore(context))
    .build()

return ApolloClient.Builder()
    .serverUrl("http://10.0.2.2:4000/graphql")
    .okHttpClient(okHttpClient)
    .build()

3. 验证与调试

添加日志拦截器查看 Cookie 的收发情况,确认后端返回的 Set-Cookie 头是否被正确保存,后续请求是否携带 Cookie 头:

import okhttp3.logging.HttpLoggingInterceptor

val loggingInterceptor = HttpLoggingInterceptor().apply {
    level = HttpLoggingInterceptor.Level.HEADERS // 仅打印头信息,避免敏感数据泄露
}

val okHttpClient = OkHttpClient.Builder()
    .addInterceptor(loggingInterceptor)
    .cookieJar(PersistentCookieStore(context))
    .build()

4. 检查环境与权限适配

  • 确保 AndroidManifest.xml 中添加了网络权限:
    <uses-permission android:name="android.permission.INTERNET"/>
    
  • 后端 Cookie 配置适配本地测试环境:secure: false 和 sameSite: 'lax' 符合 http://10.0.2.2 的非生产环境要求,无需修改。

额外注意事项

  • 若你的应用跨多个域名请求,需调整 PersistentCookieStore 中的域名解析逻辑,确保不同域名的 Cookie 独立存储。
  • 对于 Android 12+ 版本,无需额外配置网络权限,但需确保应用的网络请求符合隐私规范。

内容的提问来源于stack exchange,提问作者Sherm13

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.23 03:43:22