How to handle cookies in httpUrlConnection using cookieManager
Ok, the right way to do it is just like that:
Get Cookies from response header and load them into cookieManager:
static final String COOKIES_HEADER = "Set-Cookie";HttpURLConnection connection = ... ;static java.net.CookieManager msCookieManager = new java.net.CookieManager();Map<String, List<String>> headerFields = connection.getHeaderFields();List<String> cookiesHeader = headerFields.get(COOKIES_HEADER);if (cookiesHeader != null) { for (String cookie : cookiesHeader) { msCookieManager.getCookieStore().add(null,HttpCookie.parse(cookie).get(0)); } }
Get Cookies from cookieManager and load them into connection:
if (msCookieManager.getCookieStore().getCookies().size() > 0) { // While joining the Cookies, use ',' or ';' as needed. Most of the servers are using ';' connection.setRequestProperty("Cookie", TextUtils.join(";", msCookieManager.getCookieStore().getCookies())); }
I've been searching/trying for days to fix my issue:cannot access protected web resources even after logging in successfully
I created the same app on iOS and didn't have the same problem because NSUrlConnection did the cookie maintenance for us behind the scene. On Android, I tried manually adding cookie
connection.setRequestProperty("Cookie", "PHPSESSID=str_from_server")
without any luck.
Finally I read this
and added the following 2 lines somewhere in the beginning of my app:
CookieManager cookieManager = new CookieManager();CookieHandler.setDefault(cookieManager);
and everything works fine now.
@David's answer is the best of the lot. Its easiest to maintain a local CookieManager and manually write into and read from the cookie store associated with this cookie manager.
This code loads the Cookies from a response into the cookie manager :
/** * Gets Cookies from the response header and loads them into cookie manager * * @param conn instance of {@link HttpURLConnection} object * @param cookieManager the cookie manager({@link CookieManager} instance) in which the cookies are to be loaded<p>In case a null object is passed, the function will not perform any action and return back to the caller. </p> */public static void loadResponseCookies(@Nullable HttpURLConnection conn,@Nullable CookieManager cookieManager) { //do nothing in case a null cokkie manager object is passed if (cookieManager == null || conn == null){ return; } List<String> cookiesHeader = conn.getHeaderFields().get(COOKIES_HEADER); if (cookiesHeader != null) { for (String cookieHeader : cookiesHeader) { List<HttpCookie> cookies; try { cookies = HttpCookie.parse(cookieHeader); } catch (NullPointerException e) { log.warn(MessageFormat.format("{0} -- Null header for the cookie : {1}",conn.getURL().toString(), cookieHeader.toString())); //ignore the Null cookie header and proceed to the next cookie header continue; } if (cookies != null) { Debug("{0} -- Reading Cookies from the response :", conn.getURL().toString()); for (HttpCookie cookie : cookies) { Debug(cookie.toString()); } if (cookies.size() > 0) { cookieManager.getCookieStore().add(null, HttpCookie.parse(cookieHeader).get(0)); } } } }}
This code populates the HttpUrlConnection object with the cookies associated with the cookie manager :
public void populateCookieHeaders(HttpURLConnection conn) { if (this.cookieManager != null) { //getting cookies(if any) and manually adding them to the request header List<HttpCookie> cookies = this.cookieManager.getCookieStore().getCookies(); if (cookies != null) { if (cookies.size() > 0) { Debug("{0} -- Adding Cookie Headers : ", url.toString()); for (HttpCookie cookie : cookies) { Debug(cookie.toString(), null); } //adding the cookie header conn.setRequestProperty(COOKIE_REQUEST_HEADER, StringUtils.join(cookies, ";")); } } }}
This is the most thread safe way to handle cookies.
I tried using a threadlocal cookiestore and an extension of CookieManager. Neither of these approaches worked in my case.