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

Android:如何通过Retrofit从响应头中获取Cookie?

嘿,作为Retrofit新手,能把Dagger、Rx、MVP这些技术栈凑到一起做登录功能,已经超棒啦!针对你说的这个场景——发送JSON格式的登录参数、后端返回true的响应体还在响应头带Cookie,我给你梳理一下具体的实现思路和代码示例,帮你踩坑:

1. 定义Retrofit接口

首先要写一个符合需求的Retrofit接口,因为要同时获取响应体和响应头,我们得让接口返回Observable<Response<Boolean>>(而不是直接返回Boolean),这样就能拿到完整的响应信息:

// 如果你用Java,语法类似,把data class换成POJO就行
interface AuthService {
    @POST("Authentication.svc/json/Login")
    fun login(@Body loginRequest: LoginRequest): Observable<Response<Boolean>>
}

// 登录请求的实体类,字段要和后端要求的JSON键完全匹配
data class LoginRequest(
    val username: String,
    val password: String,
    val customCredential: String,
    val isPersistent: Boolean
)
2. 在MVP Presenter中处理请求

结合RxJava的线程调度,在Presenter里发起请求,同时处理响应体和响应头的Cookie:

class LoginPresenter(
    private val authService: AuthService,
    private val view: LoginContract.View,
    private val context: Context
) : LoginContract.Presenter {
    private val compositeDisposable = CompositeDisposable()

    override fun performLogin(username: String, password: String, customCredential: String) {
        val loginReq = LoginRequest(username, password, customCredential, false)
        val disposable = authService.login(loginReq)
            .subscribeOn(Schedulers.io()) // 网络请求在IO线程执行
            .observeOn(AndroidSchedulers.mainThread()) // 结果回调到主线程更新UI
            .subscribe(
                { response ->
                    if (response.isSuccessful && response.body() == true) {
                        // 登录成功,提取响应头里的Cookie
                        val cookieHeader = response.headers().get("Set-Cookie")
                        cookieHeader?.let { saveAuthCookie(it) }
                        view.onLoginSuccess()
                    } else {
                        view.onLoginFailed("登录失败:后端返回非成功状态")
                    }
                },
                { error ->
                    error.printStackTrace()
                    view.onLoginFailed("网络出错:${error.message ?: "未知错误"}")
                }
            )
        compositeDisposable.add(disposable)
    }

    // 把Cookie保存到SharedPreferences,方便后续请求携带
    private fun saveAuthCookie(cookie: String) {
        val sharedPref = context.getSharedPreferences("AppAuthPrefs", Context.MODE_PRIVATE)
        sharedPref.edit().putString("AUTH_COOKIE", cookie).apply()
    }

    // 页面销毁时清理Rx订阅,防止内存泄漏
    override fun onDestroy() {
        compositeDisposable.dispose()
    }
}
3. 配置Retrofit(结合Dagger依赖注入)

要确保Retrofit配置了Gson转换器(用来序列化/反序列化JSON)和RxJava适配器(让接口返回Observable),同时可以加上日志拦截器来输出你贴的那种请求日志:

@Module
class NetworkModule {
    @Provides
    fun provideGson(): Gson = GsonBuilder().create()

    @Provides
    fun provideOkHttpClient(): OkHttpClient {
        // 配置日志拦截器,对应你贴的请求日志
        val loggingInterceptor = HttpLoggingInterceptor { msg ->
            Log.d("Payesh", msg)
        }.setLevel(HttpLoggingInterceptor.Level.BODY)

        return OkHttpClient.Builder()
            .addInterceptor(loggingInterceptor)
            .build()
    }

    @Provides
    fun provideRetrofit(gson: Gson, okHttpClient: OkHttpClient): Retrofit {
        return Retrofit.Builder()
            .baseUrl("http://test.com/")
            .client(okHttpClient)
            .addConverterFactory(GsonConverterFactory.create(gson))
            .addCallAdapterFactory(RxJava2CallAdapterFactory.create())
            .build()
    }

    @Provides
    fun provideAuthService(retrofit: Retrofit): AuthService = retrofit.create(AuthService::class.java)
}
几个关键注意点
  • 如果后续接口需要携带这个Cookie,记得给OkHttpClient加一个请求拦截器,把保存的Cookie放到请求头里
  • 响应头里的Set-Cookie可能有多个值,如果你需要全部获取,可以用response.headers("Set-Cookie")拿到一个列表
  • 如果实体类字段和JSON键名不一致,记得用@SerializedName("键名")注解来映射

内容的提问来源于stack exchange,提问作者Cyrus the Great

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.21 07:47:31