Как обрабатывать куки в httpUrlConnection с помощью cookieManager
У меня есть запрос к серверу, который возвращает несколько файлов cookie, например:
Вот как я храню эти куки в cookieManager:
HttpURLConnection connection = ... ;
static java.net.CookieManager msCookieManager = new java.net.CookieManager();
msCookieManager.put(COOKIES_URI, connection.getHeaderFields());
Вот как я добавляю эти куки в следующее соединение:
connection.setRequestProperty("Cookie",
msCookieManager.getCookieStore().get(COOKIES_URI).toString());
Это правильный способ получить куки из cookieManager? Я уверен, что есть лучший...
5 ответов
Хорошо, правильный способ сделать это так:
Получить куки из заголовка ответа и загрузить их в 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));
}
}
Получите Cookies из cookieManager и загрузите их в соединение:
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()));
}
Я искал / пытался несколько дней, чтобы решить мою проблему: не могу получить доступ к защищенным веб-ресурсам даже после успешного входа в систему
Я создал такое же приложение на iOS, и у меня не было той же проблемы, потому что NSUrlConnection поддерживал нас за кулисами. На Android я пытался вручную добавить cookie
connection.setRequestProperty("Cookie", "PHPSESSID=str_from_server")
без удачи.
Наконец то прочитал
и добавил следующие 2 строки где-то в начале моего приложения:
CookieManager cookieManager = new CookieManager();
CookieHandler.setDefault(cookieManager);
и теперь все отлично работает.
@ Дэвид - лучший ответ. Проще всего поддерживать локальный CookieManager и вручную записывать и читать из хранилища cookie, связанного с этим менеджером cookie.
Этот код загружает Cookies из ответа в менеджер cookie:
/**
* 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));
}
}
}
}
}
Этот код заполняет объект HttpUrlConnection файлами cookie, связанными с менеджером файлов cookie:
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, ";"));
}
}
}
}
Это самый надежный способ обработки файлов cookie.
Я попытался использовать локальный cookie-магазин и расширение CookieManager. Ни один из этих подходов не работал в моем случае.
Другие ответы подходят для их контекста, но никто не говорит очевидного: CookieHandler автоматически обрабатывает ваши файлы cookie в большинстве случаев. Чтобы просто поддерживать файлы cookie от одного запроса к другому - например, для поддержания сеанса сервера - этой строки кода достаточно:
CookieHandler.setDefault(new CookieManager(null, CookiePolicy.ACCEPT_ALL));
Обязательно запустите его один раз перед первым запросом с помощью UrlConnection.
Теперь я сам не занимаюсь управлением файлами cookie, и все данные моего сеанса сервера безупречно поддерживаются от запроса к запросу.
Я сумасшедший? Почему в Интернете молчат об этом? Я даже не могу найти его в документации.
Принятый ответ может сработать, но я нашел более простое решение. Решение Gold Thumb не сработало в моем случае. Смотрите мой ответ, соединяющий webView & httpUrlConnection
С помощью java.net.HttpURLConnection
и заводная, просто добавь URLConnection#addRequestProperty(String key, String value)
внутри with
закрытие.
import java.net.HttpURLConnection
HttpURLConnection createRequest(String chatRequestBody) {
HttpURLConnection httpChatRequest = new URL("${endpoint}").openConnection() as HttpURLConnection
httpChatRequest.with {
doOutput = true
requestMethod = 'POST'
//headers
addRequestProperty("Content-Type", "application/json")
addRequestProperty("Client-Platform", "android")
//cookies
addRequestProperty("Cookie", "cookie_key1=cookie_value1,cookie_key2=cookie_value2")
getOutputStream().write(chatRequestBody.getBytes("UTF-8"))
}
httpChatRequest
}