如何从Retrofit和OkHttp的响应中获取cookie?

22

我正在尝试从API响应中检索Cookie值,以通过将Cookie值设置为新的API调用来维护后端会话,以防止APP关闭:

PostMan RestClient的API调用响应: enter image description here

RetrofitClient.java

public static Retrofit getClient() {

    if (checkClient()) {
        return getRetrofit();
    }

    HttpLoggingInterceptor interceptor = new HttpLoggingInterceptor();
    interceptor.setLevel(HttpLoggingInterceptor.Level.BODY);
    CookieHandler cookieHandler = new CookieManager();

    okhttp3.OkHttpClient client = new okhttp3.OkHttpClient.Builder().addNetworkInterceptor(interceptor)
            .cookieJar(new JavaNetCookieJar(cookieHandler))
            .connectTimeout(10, TimeUnit.SECONDS)
            .writeTimeout(10, TimeUnit.SECONDS)
            .readTimeout(30, TimeUnit.SECONDS)
            .build();

    Gson gson = new GsonBuilder()
            .setLenient()
            .create();

    retrofit = new Retrofit.Builder()
            .baseUrl(BASE_URL)
            .addConverterFactory(GsonConverterFactory.create(gson))
            .client(client)
            .build();
    return retrofit;
}

API 调用

private void userLogin(String username, String password) {
    Retrofit retrofit = RetrofitClient.getClient();

    final LoginServices loginServices = retrofit.create(LoginServices.class);
    Call<LoginResponse> call = loginServices.userLogin(username, password);

    call.enqueue(new Callback<LoginResponse>() {
        @Override
        public void onResponse(Call<LoginResponse> call, Response<LoginResponse> response) {
            Log.d("Response code:", "===========" + response.code());

            Log.d("==Cookie==1===", "==="+response.raw().request().headers().get("Cookie"));
            Log.d("==Cookie==2==", "==="+response.headers().get("Cookie"));
            Log.d("==Content-Type====", "==="+response.headers().get("Content-Type"));

        }

        @Override
        public void onFailure(Call<LoginResponse> call, Throwable t) {
            Log.e("TAG", "=======onFailure: " + t.toString());
            t.printStackTrace();
            // Log error here since request failed
        }
    });
}

日志:

Response code:: ===========200
==Cookie==1===: ===null
==Cookie==1===: ===null
==Content-Type====: ===application/json

我也尝试了其他各种方法,但都没有起作用。请帮忙!


response.raw().headers().get("Cookie") 尝试一下 - Manthan Patel
已经尝试过了,@ManthanPatel,但是没有起作用。 - Anurag Dhunna
@AnuragDhunna,请参考此gist - Jay
@whenthemorningcomes不起作用 :( - Anurag Dhunna
4个回答

19
List<String> Cookielist = response.headers().values("Set-Cookie");
String jsessionid = (Cookielist .get(0).split(";"))[0];

这对我有用,虽然不是完美的解决方案,但它起作用了


1
在我的情况下,我需要执行以下操作才能获得它。List<String> Cookielist = response.headers().values("Set-Cookie"); String jsessionid = (Cookielist.get(0).split(";"))[0].split("=")[1]; - Madhu Tomy

15

头部名称是"Set-Cookie"而不是"Cookie",顺便说一下

你所采取的方法不正确。如果你想保存Cookie,你可以创建一个拦截器并保存Cookie,在需要使用时再使用。

这里你需要做的是首先创建一个拦截器。

public class ReceivedCookiesInterceptor implements Interceptor {

PreferencesHelper preferencesHelper;

public ReceivedCookiesInterceptor(Context context) {
    FineractApplication.get(context).getComponent().inject(this);
    preferencesHelper = PreferencesHelper(context)
}

@Override
public Response intercept(Chain chain) throws IOException {
    Response originalResponse = chain.proceed(chain.request());

    if (!originalResponse.headers("Set-Cookie").isEmpty()) {
        HashSet<String> cookies = new HashSet<>();
        for (String header : originalResponse.headers("Set-Cookie")) {
            cookies.add(header);
        }
        // Save the cookies (I saved in SharedPrefrence), you save whereever you want to save
        preferencesHelper.putStringSet(PreferenceKey.PREF_KEY_COOKIES, cookies);
    }
    return originalResponse;
  }
}

在这里,我们正在保存您收到的所有 cookie。

现在您有了 cookie,是时候使用它了。

无论您想在哪里使用它,只需获取您之前保存的 cookie 即可。

 HashSet<String> cookies = (HashSet<String>) preferencesHelper.getStringSet(
                        PreferenceKey.PREF_KEY_COOKIES);
        if (cookies != null) {
            for (String cookie: cookies) {  
                // Use this cookie whereever you wanna use.               
                Log.d("Cookie", cookie);                 
            }
        }

祝你好运


2
嗨,我从Gist中跟随了这个链接https://gist.github.com/nikhiljha/52d45ca69a8415c6990d2a63f61184ff。每次我查询服务器时,我是否都需要调用AddCookieInterceptor和ReceiveCookieInterceptor?例如:我的登录查询将使用哪个拦截器?然后我有第二个查询,比如获取一些数据,我将使用哪个拦截器?请回复。谢谢。 - Maki

3
尝试使用response.headers().get("Set-Cookie"))

6
这不完全正确。要获取所有cookie,使用response.headers().values("Set-Cookie")),它将返回一个List<String>,应包含所有cookie。 - Bharath

0
我最近改用了一种更简单的方式来使用OkHttp和Retrofit接收和发送cookies,使用了CookieJar接口。
首先,创建一个类并实现CookieJar接口及其函数。在这个类中,你可以接收和发送cookies。
import okhttp3.Cookie
import okhttp3.CookieJar
import okhttp3.HttpUrl

class MyCookieJar : CookieJar {

    val cookieStorage = CookieDataStore()

    override fun saveFromResponse(url: HttpUrl, cookies: List<Cookie>) {
        cookieStorage.storeCookies(cookies)
    }

    override fun loadForRequest(url: HttpUrl): List<Cookie> {
        return cookieStorage.getCookies()
    }

} 

然后将MyCookieJar引入到你的OkHttpClient中:
val okHttpClient = OkHttpClient.Builder()
        .cookieJar(MyCookieJar())
        .build()

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接