Kotlin Jetpack Compose中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
相关产品推荐
相关产品推荐

