Русский
Русский
English
Статистика
Реклама

Cookiemanager

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

29.06.2020 22:07:32 | Автор: admin
Допустим, что нам надо подключиться к серверу, авторизоваться и поддерживать сессию. В браузере это выглядит следующим образом:
  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 в каждом запросе.


Рассмотрим, как это можно реализовать на Java и на Python.



Содержание:




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



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

Вся задача решается следующим скриптом:
import requestssession = requests.session()  #создаём сессиюurl = "http://localhost:8080/login"session.get(url)   #получаем cookiedata = {"username": "Fox", "password": "123"} response = session.post(url, data=data) #логинимся


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

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



Поиски библиотеки для работы с сетью на Java приводят сразу к нескольким библиотекам. Например, java.net, Apache HttpClient и OkHttp3.

Я остановился на 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) {    content.append(inputLine);}


После этого наш 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");


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

Нужна эта строчка кода для открытия исходящего потока. Забавно, что без этой строки мы получим следующее сообщение:
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) {    content.append(inputLine);String cookie = con.getHeaderField("Set-Cookie").split(";")[0];}


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

// создаём запросurl = new URL("http://localhost:8080/login");con = (HttpURLConnection) url.openConnection();con.setRequestMethod("POST");//указываем headers и cookiecon.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();//считываем и получаем второе cookieBufferedReader 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);


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

Категории

Последние комментарии

  • Имя: Макс
    24.08.2022 | 11:28
    Я разраб в IT компании, работаю на арбитражную команду. Мы работаем с приламы и сайтами, при работе замечаются постоянные баны и лаги. Пацаны посоветовали сервис по анализу исходного кода,https://app Подробнее..
  • Имя: 9055410337
    20.08.2022 | 17:41
    поможем пишите в телеграм Подробнее..
  • Имя: sabbat
    17.08.2022 | 20:42
    Охренеть.. это просто шикарная статья, феноменально круто. Большое спасибо за разбор! Надеюсь как-нибудь с тобой связаться для обсуждений чего-либо) Подробнее..
  • Имя: Мария
    09.08.2022 | 14:44
    Добрый день. Если обладаете такой информацией, то подскажите, пожалуйста, где можно найти много-много материала по Yggdrasil и его уязвимостях для написания диплома? Благодарю. Подробнее..
© 2006-2024, personeltest.ru