【问题标题】:How to get more than one Set-Cookie header from response using Retrofit/OkHttpClient?如何使用 Retrofit/OkHttpClient 从响应中获取多个 Set-Cookie 标头?
【发布时间】:2016-03-14 20:46:40
【问题描述】:

我正在尝试在 Android 上使用 Retrofit/OkHttpClient 进行身份验证调用。服务器使用两个 Set-Cookie 标头响应 302,并且 okHttp 处理重定向。我发现了一些使用 cookieManager 获取这些 cookie 的技巧。但似乎 cookieManager 只读取了一个 Set-Cookie 标头。

我在服务器响应标头中有这个:

Set-Cookie:first=1
Set-Cookie:second=2

这是我的 cookieManager 部分:

private static CookieManager cookieManager;
(...)
OkHttpClient okHttpClient = new OkHttpClient();
okHttpClient.setFollowSslRedirects(true);
okHttpClient.setAuthenticator(new NTLMAuthenticator(user, passwd, domain));

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

并处理 Set-Cookie 标头:

public void checkForSetCookies() {
    List<retrofit.client.Header> headerList = new ArrayList<>();
    List <HttpCookie> cookies = cookieManager.getCookieStore().getCookies();
    //List cookies has only one cookie:  first=1
    for (HttpCookie cookie : cookies) {
        retrofit.client.Header header = new retrofit.client.Header("Set-Cookie", cookie.toString());
        headerList.add(header);
    }

    if (headerList.size() > 0) {
        Commons.setLoginRetofitCookies(headerList);
    }
}

有没有办法强制 cookieManager 读取我的两个 Set-Cookie 标头?

提前感谢您的帮助。

【问题讨论】:

    标签: android cookies retrofit okhttp


    【解决方案1】:

    我想我解决了这个问题。 CookieManager 类正在将响应头解析为列表:

    List<HttpCookie> cookies = parseCookie(responseHeaders);
    

    因此第二个 cookie 被覆盖。

    我决定创建 MyCookieManager 内部类并重写其 put 方法以将 cookie 值放入字符串列表。我调用 super 方法来做所有的 headers 验证。

    class MyCookieManager extends CookieManager {
    
        @Override
        public void put(URI uri, Map<String, List<String>> stringListMap) throws IOException {
            super.put(uri, stringListMap);
            if (stringListMap != null && stringListMap.get("Set-Cookie") != null)
                for (String cookieValue: stringListMap.get("Set-Cookie")) {
                    cookiesStrings.add(cookieValue);
                }
        }
    }
    

    现在它工作正常:)

    【讨论】:

      【解决方案2】:

      从响应中获取多个“Set-Cookie”标头:

       Call<LoginResponse> call = apiService.login(loginRequest);
          call.enqueue(new Callback<LoginResponse>() {
              @Override
              public void onResponse(Call<LoginResponse> call, Response<LoginResponse> response) {
                  showProgress(false);
                  if (response.body() != null) {
      
                      LoginResponse loginResponse = response.body();
                      //Get headers from response
                      Headers headerResponse = response.headers();
                      //convert header to Map
                      Map<String, List<String>> headerMapList = headerResponse.toMultimap();
                      //Get List of "Set-Cookie" from Map 
                      List<String> allCookies = headerMapList.get("Set-Cookie");
                      String cookieval = "";
                      for (int i = 1; i < allCookies.size(); i++) {
                          allCookies.get(i);
                          //concat all cookies in cookieval.
                          cookieval = cookieval + allCookies.get(i);
                      }
                      //Save cookies value in Application class.
                      ((AppConfig) getApplication()).setCookies(cookieval);
      
                      ((AppConfig) getApplication()).setUserInfo(loginResponse);
                      if (loginResponse.getStatus().equals("ok")) {
                          startActivity(new Intent(LoginActivity.this, MainActivity.class));
                          mAuthTask = true;
                          finish();
                      } else {
                          mPasswordView.setError(getString(R.string.error_incorrect_password));
                          mPasswordView.requestFocus();
                      }
                  }
              }
      
              @Override
              public void onFailure(Call<LoginResponse> call, Throwable t) {
                  Log.d(TAG, "onFailure: ");
                  mAuthTask = false;
              }
          });
      

      传递其他服务中的所有cookie(例如注销服务)

       @Headers({"Content-Type: application/json"})
      @POST("request/get/user/logout")
      Call<LogoutResponse> logout(@Header("Cookie") String cookie);
      

      在Api接口中添加这段代码

      现在调用注销服务,如:

      Call<LogoutResponse> call = apiService.logout(((AppConfig) getApplication()).getCookies());
          call.enqueue(new Callback<LogoutResponse>() {
              @Override
              public void onResponse(Call<LogoutResponse> call, Response<LogoutResponse> response) {
                  if(response.body() != null){
                      LogoutResponse logoutResponse = response.body();
                      if (logoutResponse.getStatus().equals("ok")) {
                          finish();
                          startActivity(new Intent(MainActivity.this, LoginActivity.class));
                      }
                  }
              }
      
              @Override
              public void onFailure(Call<LogoutResponse> call, Throwable t) {
                  Log.d(TAG, "onFailure: ");
              }
          });
      

      【讨论】:

        【解决方案3】:

        您可以使用 Kotlin 编写扩展函数。

        fun Headers.getCookies(): String? {
            var cookieString: String? = null
            this.toMultimap()["Set-Cookie"]?.forEach {
            cookieString += it
            }
            return cookieString
        }
        

        【讨论】:

          【解决方案4】:

          您可以使用response.headers().values("some_header") 来获取标题的多个值

             val authCookies = mutableMapOf<String, String>()
             val response = restManager.login(AuthDto().apply {
                      clientId = agent.clientId
                      apiKey = "awesome_api_key"
                  }).execute()
                  response.headers().values("Set-Cookie").forEach {
                      if (it.startsWith("auth=")) {
                          authCookies["auth"] = it
                      } else {
                          authCookies["refresh"] = it
                      }
                  }
          

          【讨论】:

            猜你喜欢
            • 1970-01-01
            • 2014-02-26
            • 2021-10-21
            • 2021-02-03
            • 1970-01-01
            • 2015-02-10
            • 2011-01-28
            • 2015-09-11
            • 1970-01-01
            相关资源
            最近更新 更多