RETROFIT & AUTH COOKIE

2020-02-17 07:30发布

问题:

I need to know how to add an authorization cookie header in retrofit. I have seen advice like using request intercepter etc. Below is what I am trying, but is this correct? First of all I already needed a RequestAdatper to get the session id the first time around. This can only be set by the builder of the request adapter. But I needed to make a request just to get the session id in the first place. Do I need two rest adapters one to get the sessionId and another one after I have obtained it. What I really need is a method on adapter to set the cookie after I get it but it does not appear to be such a method. This is getting awkward. How do I set authorization cookie in retrofit? I don't see this in FAQ or tutorials.

RequestInterceptor requestInterceptor = new RequestInterceptor()
{   
   @Override
   public void intercept(RequestFacade request) {
        request.addHeader("Set-Cookie", "sessionId="+sessionIdentifier);
   }
 };

RestAdapter.Builder().setServer(serverURL)..setRequestIntercepter(requestIntercepter).build();  

// but I don't have sessionId when this is first issued ???

回答1:

Keep a reference to the interceptor and treat it as a singleton like you would be RestAdapter itself.

public class ApiHeaders implements RequestInterceptor {
  private String sessionId;

  public void setSessionId(String sessionId) {
    this.sessionId = sessionId;
  }

  public void clearSessionId() {
    sessionId = null;
  }

  @Override public void intercept(RequestFacade request) {
    if (sessionId != null) {
      request.setHeader(...);
    }
  }
}

Now, simply call setSessionId after your authentication call. All subsequent requests will include the header.



回答2:

You can get the cookies like this

 public 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 string : stringListMap.get("Set-Cookie")) {
                if (string.contains("JSESSIONID")) {
                    Preference.getInstance().setSessionId(string);
                }
            }
    }
}

Use this to set the CookieHandler

 MyCookieManager myCookieManager = new MyCookieManager();
        CookieHandler.setDefault(myCookieManager);

and then use it like this in your request Interceptor

 String sessionId = preference.getSessionId();
                    if (sessionId != null)
                        requestFacade.addHeader(Cookie, sessionId);


回答3:

Step 1. Parse Response headers. Call this method inside your Callback in overriden success method.

    /**
     * Method extracts cookie string from headers
     * @param response with headers
     * @return cookie string if present or null
     */
    private String getCookieString(Response response) {
        for (Header header : response.getHeaders()) {
            if (null!= header.getName() && header.getName().equals("Set-Cookie")) {
                return header.getValue();
            }
        }
        return null;
    }

Step 2. Write some static class or singleton to keep cookies and your RequestInterceptor instance. Inside RequestInterceptor override intercept method to add your cookies to Header.

public class RestAdapter {
    private static String cookies;

    public static String getCookies() {
        return cookies;
    }

    public static void setCookies(String cookies) {
        RestAdapter.cookies = cookies;
    }

    /**
     * Injects cookies to every request
     */
    private static final RequestInterceptor COOKIES_REQUEST_INTERCEPTOR = new RequestInterceptor() {
        @Override
        public void intercept(RequestFacade request) {
            if (null != cookies && cookies.length() > 0) {
                request.addHeader("Cookie", cookies);
            }
        }
    };

    public static final RestInterface getService() {
        return new RestAdapter.Builder()
                .setEndpoint(Config.ENDPOINT)
                .setRequestInterceptor(COOKIES_REQUEST_INTERCEPTOR)
                .setConverter(new JacksonConverter())
                .setLogLevel(RestAdapter.LogLevel.NONE)
                .build()
                .create(RestInterface.class);
    }
}


回答4:

According to @sbtgE's answer, but with some corrections. CookieHandler.getDefault() may be null, so I use CookieManager.

app's build.gradle:

dependencies {
    ...
    compile 'com.squareup.okhttp3:okhttp-urlconnection:3.4.1'
}

Setting up Retrofit:

service = new Retrofit.Builder()
        .baseUrl(/* your base URL */)
        .addConverterFactory(/* your favourite converter */)
        .client(
                new OkHttpClient.Builder()
                        // this line is the important one:
                        .cookieJar(new JavaNetCookieJar(new CookieManager()))
                        .build())
        .build()
        .create(YourInterface.class);


回答5:

Simple solution using lib. compile com.squareup.okhttp3:okhttp-urlconnection:3.2.0.

JavaNetCookieJar jncj = new JavaNetCookieJar(CookieHandler.getDefault()); OkHttpClient.Builder().cookieJar(jncj).build();