Java httpurlconnection get cookies

Thomas Goirand’s tech log

Using cookies, HttpURLConnection and InputStream in Java

java.net.HttpCookie has been introduced in Java 6. If you don’t need JSoup or HTTP Common, the standard API provides an easy way to collect cookies from an HTTP connection.

CookieManager cm = new CookieManager(); CookieHandler.setDefault(cm);

As far as I know, there isn’t a convenient way to provide a CookieStore to an HttpURLConnection and the programmer has to set values and properties of the HTTP header by himself.
A way to avoid that, is to create an InputStream class which would behave just like FileOutputStream but for HTTP connections.

import java.io.DataOutputStream; import java.io.IOException; import java.io.InputStream; import java.net.HttpCookie; import java.net.HttpURLConnection; import java.net.URL; import java.util.List; import sun.misc.BASE64Encoder; public class HttpInputStream extends InputStream < private InputStream is; private HttpURLConnection conn; public final static String USERAGENT_FIREFOX_5_MAC = "Mozilla/5.0 (Macintosh; U; Intel Mac OS X 10.6; fr; rv:1.9.2.13) Gecko/20101203 Firefox/3.6.13 GTB7.1"; private int TIMEOUT = 10000; public HttpInputStream(URL url, String username, String password, HttpParameters params, Listcookies) throws IOException < openConnection(url, USERAGENT_FIREFOX_5_MAC); setCookies(cookies); authenticate(username, password); setParameters(params); connect(); >public HttpInputStream(URL url, String username, String password, HttpParameters params) throws IOException < openConnection(url, USERAGENT_FIREFOX_5_MAC); authenticate(username, password); setParameters(params); connect(); >public HttpInputStream(URL url, HttpParameters params, List cookies) throws IOException < openConnection(url, USERAGENT_FIREFOX_5_MAC); setCookies(cookies); setParameters(params); connect(); >public HttpInputStream(URL url, HttpParameters params) throws IOException < openConnection(url, USERAGENT_FIREFOX_5_MAC); setParameters(params); connect(); >public HttpInputStream(URL url, List cookies) throws IOException < openConnection(url, USERAGENT_FIREFOX_5_MAC); setCookies(cookies); connect(); >private void authenticate(String username, String password) < if (username != null) < BASE64Encoder enc = new BASE64Encoder(); String userpassword = username + ":" + password; String encodedAuthorization = enc.encode(userpassword.getBytes()); conn.setRequestProperty("Authorization", "Basic " + encodedAuthorization); >> private void openConnection(URL url, String useragent) throws IOException < conn = (HttpURLConnection) url.openConnection(); if (useragent != null) < conn.setRequestProperty("User-agent", useragent); >conn.setDoOutput(true); conn.setReadTimeout(TIMEOUT); > protected void setCookies(List cookies) throws IOException < if (cookies != null) < for (HttpCookie cookie : cookies) < if (log.isDebugEnabled()) log.debug("set cookie"); conn.setRequestProperty("Cookie", cookie.getName() + "=" + cookie.getValue()); >> > private void setParameters(HttpParameters params) throws IOException < if (params != null) < conn.setRequestMethod(params.getMethod().toString()); conn.setDoInput(true); if (params.getMethod() == HttpParameters.HttpMethod.POST) < conn.setDoOutput(true); DataOutputStream wr = new DataOutputStream(conn.getOutputStream()); wr.writeBytes(params.getEncodedParamaters()); wr.flush(); wr.close(); >> else < conn.setRequestMethod("GET"); >> private void connect() throws IOException < conn.connect(); is = conn.getInputStream(); >@Override public int read() throws IOException < return is.read(); >@Override public void close() throws IOException < is.close(); conn.disconnect(); >@Override public int read(byte[] b, int off, int len) throws IOException < return is.read(b, off, len); >@Override public int read(byte[] b) throws IOException < return is.read(b); >>
import java.io.UnsupportedEncodingException; import java.net.URLEncoder; import java.util.LinkedHashMap; import java.util.Map; public class HttpParameters < protected Mapparams; protected HttpMethod method; protected String CHARSET = "UTF-8"; public HttpParameters(HttpMethod method) < this.method = method; params = new LinkedHashMap(); > public HttpParameters(Map params, HttpMethod method) < this.params = params; this.method = method; >public void addParameter(String key, String value) < params.put(key, value); >public String getEncodedParamaters() throws UnsupportedEncodingException < StringBuilder sb = new StringBuilder(); boolean first = true; for (String key : params.keySet()) < if (!first) < sb.append("&"); >first = false; sb.append(URLEncoder.encode(key, CHARSET)); sb.append("="); sb.append(URLEncoder.encode(params.get(key), CHARSET)); > return sb.toString(); > public HttpMethod getMethod() < return method; >public void setMethod(HttpMethod method) < this.method = method; >public enum HttpMethod < GET, POST, PUT, DELETE >>

Then it is easy to deal with HTTP content, URL and Cookies
i.e

CookieManager cm = new CookieManager(); CookieHandler.setDefault(cm); // authenticate and get the session cookie new HttpInputStream(new URL("http://www.foo.com/", "login", "password")).close(); // set parameters HttpParameters param = new HttpParameters(HttpParameters.HttpMethod.POST); param.addParameter("param1", "value1"); param.addParameter("param2", "value2"); // download a file using the cookie InputStream is = new HttpInputStream(new URL("http://www.foo.com/space/doc.pdf", cm.getCookieStore().getCookies()), param); OutputStream os = new FileOutputStream(new File("doc.pdf")); int read; while ((read = os.read()) != -1) is.write(read); is.close(); os.close();

Источник

Читайте также:  Php define and use

Подключение к session в Java и Python. HttpURLConnection и CookieManager (Java). Requests(Python)

Допустим, что нам надо подключиться к серверу, авторизоваться и поддерживать сессию. В браузере это выглядит следующим образом:

  1. На адрес http://localhost:8080/login отправляется пустой GET запрос.
  2. Сервер присылает формочку для заполнения логина и пароля, а также присылает Cookie вида «JSESSIONID=094BC0A489335CF8EE58C8E7846FE49B».
  3. Заполнив логин и пароль, на сервер отправляется POST запрос с полученной ранее Cookie, со строкой в выходном потоке «username=Fox&password=123». В Headers дополнительно указывается «Content-Type: application/x-www-form-urlencoded».
  4. В ответ сервер нам присылает новую cookie c новым «JSESSIONID=». Сразу же происходит переадресация на http://localhost:8080/ путём GET запроса с новой Cookie.
  5. Далее можно спокойно использовать остальное API сервера, передавая последнее Cookie в каждом запросе.

Реализация на Python. Requests

При выборе библиотеки для работы с сетью на Python большинство сайтов будет вам рекомендовать библиотеку requests , которая полностью оправдывает свой лозунг:

Вся задача решается следующим скриптом:

import requests session = requests.session() #создаём сессию url = "http://localhost:8080/login" session.get(url) #получаем cookie data = response = session.post(url, data=data) #логинимся 

Заметим, что махинации с Cookie и переадресацией происходят под капотом, прямо как в браузере. Так же можно отметить, что если завести ещё одну переменную session2, то можно держать активными сразу два подключения.

Реализация на Java, HttpURLConnection и CookieManager

Поиски библиотеки для работы с сетью на Java приводят сразу к нескольким библиотекам.

Я остановился на HttpURLConnection (java.net). Плюсами данной библиотеки является то, что это библиотека «из-под коробки«, а так же, если надо написать приложение под android, на официальном сайте есть документация. Минусом является очень большой объём кода. (После Python это просто боль).

Итак, начнём. По документации для работы с сессиями можно использовать CookieManager:

CookieManager cookieManager = new CookieManager(null, CookiePolicy.ACCEPT_ALL); CookieHandler.setDefault(cookieManager); 

Что нужно отметить, используя такой подход:

  • «CookiePolicy.ACCEPT_ALL» указывает, что надо работать со всеми cookie.
  • Переменная cookieManager далее нигде не будет использоваться. Она контролирует все подключения, и, если необходимо поддерживать несколько активных сессий, необходимо будет в этой одной переменной руками менять Cookie
 CookieHandler.setDefault(new CookieManager(null, CookiePolicy.ACCEPT_ALL)); 

Пункт 1 и 2. Выполним GET запрос для получения первой Cookie:

URL url = new URL("http://localhost:8080/login"); HttpURLConnection con = (HttpURLConnection) url.openConnection(); con.setRequestMethod("GET"); BufferedReader in = new BufferedReader(new InputStreamReader(con.getInputStream())); String inputLine; final StringBuilder content = new StringBuilder(); while ((inputLine = in.readLine()) != null)

После этого наш cookieManager будет содержать Cookie с сервера и автоматически подставит её в следующий запрос.

Веселье начинается с POST запросом.

url = new URL("http://localhost:8080/login"); con = (HttpURLConnection) url.openConnection(); con.setRequestMethod("POST"); 

Нужно записать в Headers «Content-Type: application/x-www-form-urlencoded».

Почему метод называется setRequestProperty, а не setHeaders (или addHeaders) при наличии метода getHeaderField, остаётся загадкой.

con.setRequestProperty("Content-Type", "application/x-www-form-urlencoded"); 

Далее идёт код, который непонятно по каким причинам не засунут под капот библиотеки.

Нужна эта строчка кода для открытия исходящего потока. Забавно, что без этой строки мы получим следующее сообщение:

Exception in thread «main» java.net.ProtocolException: cannot write to a URLConnection if doOutput=false — call setDoOutput(true)

Открываем исходящий поток и записываем туда логин и пароль:

final DataOutputStream out = new DataOutputStream(con.getOutputStream()); out.writeBytes("username=Fox&password=123"); out.flush(); out.close(); 

Остаётся считать ответ с уже перенаправленного запроса.

Реализация на Java, HttpURLConnection без CookieManager

Можно реализовать и без CookieManager и самому контролировать перемещение cookie.
Пункт 1 и 2. Вынимаем cookie.

URL url = new URL("http://localhost:8080/login"); HttpURLConnection con = (HttpURLConnection) url.openConnection(); con.setRequestMethod("GET"); BufferedReader in = new BufferedReader(new InputStreamReader(con.getInputStream())); String inputLine; final StringBuilder content = new StringBuilder(); while ((inputLine = in.readLine()) != null)

Далее отправляем POST запрос, только на этот раз вставив cookie и отключив автоматическое перенаправление, т.к. перед ним надо успеть вытащить новое cookie:

// создаём запрос url = new URL("http://localhost:8080/login"); con = (HttpURLConnection) url.openConnection(); con.setRequestMethod("POST"); //указываем headers и cookie con.setRequestProperty("Content-Type", "application/x-www-form-urlencoded"); con.setRequestProperty("Cookie", cookie); //отключаем переадресацию con.setInstanceFollowRedirects(false); //отправляем логин и пароль con.setDoOutput(true); final DataOutputStream out = new DataOutputStream(con.getOutputStream()); out.writeBytes("username=Fox&password=123"); out.flush(); out.close(); //считываем и получаем второе cookie BufferedReader in = new BufferedReader(new InputStreamReader(con.getInputStream())); String inputLine; final StringBuilder content = new StringBuilder(); while ((inputLine = in.readLine()) != null) < content.append(inputLine); String cookie2 = con.getHeaderField("Set-Cookie").split(";")[0]; 

Далее во все запросы просто добавляем следующую строку:

con.setRequestProperty("Cookie", cookie2); 

Источник

The following code gets the cookie value from the server. It looks at the header name Set-Cookie and uses regular expression ;\\s* to split the set cookie command.

import java.net.URL; import java.net.URLConnection; // ja va2 s . c o m public class Main < public static void main(String[] argv) throws Exception < URL url = new URL("http://java2s.com"); URLConnection conn = url.openConnection(); for (int i = 0;; i++) < String headerName = conn.getHeaderFieldKey(i); String headerValue = conn.getHeaderField(i); if (headerName == null && headerValue == null) < break; > if ("Set-Cookie".equalsIgnoreCase(headerName)) < String[] fields = headerValue.split(";\\s*"); for (int j = 1; j < fields.length; j++) < if ("secure".equalsIgnoreCase(fields[j])) < System.out.println("secure=true"); > else if (fields[j].indexOf('=') > 0) < String[] f = fields[j].split(" expires".equalsIgnoreCase(f[0])) < System.out.println("expires"+ f[1]); > else if ("domain".equalsIgnoreCase(f[0])) < System.out.println("domain"+ f[1]); > else if ("path".equalsIgnoreCase(f[0])) < System.out.println("path"+ f[1]); > > > > > > > 

The code above generates the following result.

import java.net.URL; import java.net.URLConnection; // j av a 2s . c o m public class Main < public static void main(String[] argv) throws Exception < URL url = new URL("http://hostname:80"); URLConnection conn = url.openConnection(); conn.setRequestProperty("Cookie", "name1=value1; name2=value2"); conn.connect(); > > 

Next chapter.

What you will learn in the next chapter:

Источник

How to get Cookies with HttpURLConnection in Java?

When I use HttpURLConnection and try con.getHeaderField("Set-Cookie") I get this response:

__cfduid=1111111aaaaaa; expires=Wed, 19-Dec-18 06:19:46 GMT; path=/; domain=.site.com; HttpOnly 

But the browser cookies are:

__cfduid=1111111aaaaaa; _ym_uid=000000000; PHPSESSID=zzzzzzzz; _ym_isad=1; key=555 

How I can get the FULL cookie, using HttpURLConnection ? The most important cookie for me is key .

Shannon Avatar

asked Dec 19 '17 13:12

Shannon

1 Answers

The value of Set-cookie header modify or append new value to Cookies in browser. And browser delete expired cookie from cookies. The assembling work completed by browser.

When request web in java, programmer need assemble 'full' cookies by Set-cookie header in single or multi responses.

If you use HttpURLConnection , you can use CookieManager

CookieManager cookieManager = new CookieManager(); CookieHandler.setDefault(cookieManager); URL url = new URL("https://stackoverflow.com"); URLConnection connection = url.openConnection(); connection.getContent(); List cookies = cookieManager.getCookieStore().getCookies(); for (HttpCookie cookie : cookies)

When you send HTTP request, CookieManager will auto fill Cookie Header. And, the value can be directly achieved from CookieManger by domain.

Источник

Оцените статью