1

Тема: Авторизация на сайтах

По просьбе разобраться с авторизацией torrent-tv (который в данный момент недоступен, да ещё и заблокирован на территории России), пояснения как её сделать в коде буду пояснять на примере сайта 1ttv.org

Чтобы реализовать авторизацию на сайтах в коде скрипта, нужно, для начала, просмотреть как она происходит на сайте в браузере.
Для этого можно использовать любой http сниффер, например Charles.

Просмотр авторизации через браузер

  1. Запускаем Charles
  2. Открываем браузер, идём на страницу сайта. Если нужно, предварительно нужно выйти (разлогиниться) на нём, чтобы перехватить момент именно успешной авторизации.
  3. Логинимся на сайте.
  4. Идём в сниффер и смотрим, как происходили запросы (Request) и какие сервер отдал после этого ответы (Response).
  5. Находим структуре запросов http://1ttv.org и смотрим, к каким страничкам были запросы.

Смотрим как прошёл запрос:
request

Видим, что запрос идёт на страничку /auth.php. Справа открываем вкладку "Request", для удобства внизу нажимаем вкладку "Raw" и смотрим все данные, которые были отосланы на сервер.

Тут видно, что запрос идёт методом POST, сверху видны HTTP заголовки (Accept, Origin, User-Agent...), последней строкой переданы данные через этот метод. В данном примере переданы данные вида: email=<логин>&password=<пароль>&enter=%D0%92%D0%BE%D0%B9%D1%82%D0%B8.

На стороне сервера также могут проверяться заголовки приходящих запросов, чтобы запросы шли только от их сайта или проверенных источников. Поэтому нам тоже нужно будет в коде скрипта установить несколько заголовков: "Referer: http://1ttv.org/auth.php", "Origin: http://1ttv.org". Как устанавливать и передавать HTTP заголовки будет показано в коде ниже.

Иногда также полезно устанавливать User-Agent и другие заголовки. Зависит от конкретного случая.

Переключаемся на вкладку Response, чтобы посмотреть ответ на данный запрос:
request

+ Смотрим ответ при удачной авторизации

HTTP/1.1 302 Moved Temporarily
Date: Mon, 14 Dec 2015 08:57:16 GMT
Content-Type: text/html
Transfer-Encoding: chunked
Connection: keep-alive
Keep-Alive: timeout=60
Expires: Thu, 01 Jan 1970 00:00:01 GMT
Cache-Control: no-cache
Pragma: no-cache
Set-Cookie: PHPSESSID=92ec42ccac6d6d79c4e9f2323e55adf4; expires=Tue, 15-Dec-2015 08:57:15 GMT
Location: http://1ttv.org/cabinet.php
X-Frame-Options: SAMEORIGIN
X-Content-Type-Options: nosniff
X-XSS-Protection: 1; mode=block;
Server: ddos-guard.net

Тут первой строчкой видно, что в ответ приходит редирект (перенаправление) с кодом 302 Moved Temporarily. У ответов перенаправления с кодами 3xx должен быть установлен заголовок Location, в данном случае его значение: http://1ttv.org/cabinet.php

Тут же идёт установка значения Cookie. Вот это то значение нам и понадобится.

Надо сразу сказать, что тут простейший пример авторизации. В других случаях, нужно также брать не только cookie (и не обязательно их), но и другие установленные заголовки. Какие именно заголовки и значения проверяются на сервере, сразу сказать невозможно. Поэтому может потребоваться эксперименты с их установкой. В крайнем случае, вообще всё полностью повторять, как это происходит в браузере (устанавливать напрочь все заголовки).

Итого, мы посмотрели как происходит успешная авторизация через браузер и получили все данные для этого нужные.

Подготовка хитрого плана

Итак, у нас есть данные, которые нужно отправить в запросе на сервер. Нужно будет установить HTTP заголовки, как минимум: Referer: http://1ttv.org/auth.php, Origin: http://1ttv.org. Страница авторизации: /auth.php. Метод запроса должен быть POST и передать данные POST запроса.

Т.е. план такой:

  1. Сделать POST запрос на страничку http://1ttv.org/auth.php с переданными данными email=...&password=...&enter=%D0%92%D0%BE%D0%B9%D1%82%D0%B8
  2. Перехватить ответ перенаправления и получить HTTP заголовки ответа
  3. Взять оттуда значение cookie. Которое потом в следующих запросах в коде скрипта везде подставлять в Headers (в заголовки при запросе страниц сайта).

Сделать запрос мы можем функцией

HmsSendRequestEx('1ttv.org', '/auth.php', 'POST', 'application/x-www-form-urlencoded', sHeaders, sPost, 80, iFlags, sAnswHeaders, true);

Где переменные: sHeaders - будет содержать установленные заголовки ("Referer: ...", "Origin: ..."), sPost - данные POST запроса ("email=..."), iFlags - флаг настроек для избежания автоматического перенаправления (о нём в пояснениях ниже), sAnswHeaders - а в эту переменную будут получены заголовки ответа от сервера, где можно выудить интересную информацию - установку Cookies.

Вычленить нужное значение из заголовков ответа sAnswHeaders можно командой

HmsRegExMatch('(PHPSESSID=.*?);', sAnswHeaders, sCookie);

Которая, в случае успеха, по регулярному выражению найдёт в заголовках ответа sAnswHeaders значение PHPSESSID и занесёт его в переменную sCookie.

Написание кода авторизации

Для этого, я бы написал отдельную функцию, которую можно было бы вызывать, например, из главной процедуры.

+ Код функции авторизации на 1ttv.org

Function Login1TTV(): Boolean;
Var
  sName, sUser, sPass, sPost, sHeaders, sAnswHeaders, sCookie: String;
  iFlags: Integer;
Begin 
  sHeaders := 'http://1ttv.org/auth.php'+#10#13+
              'Origin: http://1ttv.org'+#10#13;
  iFlags := $00200000; // INTERNET_FLAG_NO_AUTO_REDIRECT=0x00200000
  sUser  := HmsPercentEncode(HmsUtf8Encode(mpPodcastAuthorizationUserName));
  sPass  := HmsPercentEncode(HmsUtf8Encode(mpPodcastAuthorizationPassword));
  sPost  := 'email='+sUser+'&password='+sPass+'&enter=%D0%92%D0%BE%D0%B9%D1%82%D0%B8';
  HmsSendRequestEx('1ttv.org', '/auth.php', 'POST', 'application/x-www-form-urlencoded', sHeaders, sPost, 80, iFlags, sAnswHeaders, true);
  Result := HmsRegExMatch('(PHPSESSID=.*?);', sAnswHeaders, sCookie);
  If Result Then 
    gsHeaders := gsHeaders+'Cookie: '+sCookie+#10#13
  Else 
    HmsLogMessage(2, "Ошибка авторизации на 1ttv.org");
End;

А теперь пояснения к коду

Сначала объявляются переменные, которые будут использоваться в функции (всё что перечисляется после ключевого слова Var).

Var
  sName, sUser, sPass, sPost, sHeaders, sAnswHeaders, sCookie: String;
  iFlags: Integer;

Потом в переменную sHeaders устанавливаем HTTP заголовки, которые мы будем передавать при запросе. Заголовки разделяются знаками перевода строк и каретки - #10#13.

  sHeaders := 'http://1ttv.org/auth.php'+#10#13+
              'Origin: http://1ttv.org'+#10#13;

В переменную iFlags заносим значение флага INTERNET_FLAG_NO_AUTO_REDIRECT, чтобы ответ пришёл ДО перенаправления.

Указать метод запроса (POST) и получить заголовки ответа можно только функцией HmsSendRequestEx.

И ещё раз. Параметры функции HmsSendRequestEx:

  1. '1ttv.org' - сервер, куда отправляется запрос. Указывается без протокола (http и проч) и страниц.
  2. '/auth.php' - страница запроса. Указывается без сервера. Могут быть после знака '?' указывать параметры для GET запроса.
  3. 'POST' - метод запроса. (Могут быть 'GET', 'POST', 'HEAD', 'PUT', 'DELETE')
  4. 'application/x-www-form-urlencoded' - тип запрашиваемого контента. Может принимать значения MIME типа.
  5. sHeaders - Referer + могут быть указаны дополнительные HTTP заголовки, разделённые знаками #10#13 (0x0A 0x0D или '\r\n')
  6. 80 - порт. Обычно для http порт 80, для https - 443
  7. iFlags - интернет флаги. Список значений можно посмотреть здесь (если забыли ссылку, гуглить "internet flags")
  8. sAnswHeaders - переменная, которая будет содержать HTTP заголовки ответа. Очень для нас важный параметр.
  9. true - флаг, указывающий автоматически определять запакованные ответы и распаковывать их (например, если в заголовках было указана поддержка сжатия данных Accept-Encoding: gzip, deflate)

Обычно, при запросе страниц их перенаправление происходит автоматически и в ответе мы получаем уже данные после перенаправления. Поэтому, чтобы указать, чтобы ответ пришел без автоматического перенаправления, мы используем флаг INTERNET_FLAG_NO_AUTO_REDIRECT и указываем его значение в переменной iFlags.

Функция возвращает загруженные данные (страницы), но в данном случае нам это не нужно и мы тут анализируем только HTTP заголовки ответов, которые появляются в sAnswHeaders после запроса.

Оттуда мы командной

Result := HmsRegExMatch('(PHPSESSID=.*?);', sAnswHeaders, sCookie);

получаем значение cookie PHPSESSID и запоминаем в переменной sCookie.
Полученное значение sCookie мы добавляем к глобальной переменной gsHeaders, которая будет передаваться всем запросам для загрузки страниц в дальнейшем.

 gsHeaders := gsHeaders+'Cookie: '+sCookie+#10#13

Значит, нам нужно в главной процедуре, установить значение глобальной gsHeaders. Если установлено имя пользователя в подкасте, сделать вызов нашей функции авторизации на сайте Login1TTV(), где, если всё успешно, к gsHeaders будут добавлены нужные заголовки (тут "Cookie: PHPSESSID=...") и в дальнейшем во всех функциях загрузки страниц мы можем указывать gsHeaders.

Для того, чтобы приведённый выше код работал в подкасте для 1ttv, нужно в коде скрипта по Alt+2 в самом вверху после ключевого слова Var объявить также глобальную переменную gsHeaders

var
  gsHeaders: String;

А в главной процедуре можно сделать примерно так:

  gsHeaders := 'Referer: '+mpFilePath+#10#13+
               'Origin: http://1ttv.org'+#10#13+
               'Accept-Encoding: gzip, deflate'+#10#13+
               'User-Agent: Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/43.0.2357.130 Safari/537.36'+#10#13;

  If mpPodcastAuthorizationUserName<>'' Then Login1TTV();
  
  sWebPage := HmsDownloadURL(mpFilePath, gsHeaders, True);
  if (Pos('film_selector.php', sPage)>1) then
    for i := 2 to 20 do  sWebPage := sWebPage+HmsDownloadURL(mpFilePath+'&page='+IntToStr(i), gsHeaders, True);
  sWebPage := HmsUtf8Decode(sWebPage);
  sWebPage := HmsRemoveLineBreaks(sWebPage);

Заметьте, в функции HmsDownloadURL вторым параметром мы указываем глобальную переменную gsHeaders, которая, кроме установленных заголовков, после нашей функции Login1TTV() будет содержать полученную и добавленную cookie, которая будет говорить сайту, что мы на самом деле авторизованные пользователи.

Что не понятно и глупые вопросы можно задавать тут.

Sony Bravia KDL-32CX523
Спасибо сказали: Astr811

2

Re: Авторизация на сайтах

Спасибо конечно за разъяснения, я честно признаюсь что я в ступоре, я прочитал трижды, и всё равно в непонятках. Можно как то в более доступном пошаговом варианте для чайников...Я говорю как потребитель, а не как " вы - магистр". Мне кажется что многие пользователи не такие продвинутые, хотя это наши проблемы отчасти.

LG 42LM615T / PS4

3

Re: Авторизация на сайтах

HERO1CK пишет:

Спасибо конечно за разъяснения, я честно признаюсь что я в ступоре, я прочитал трижды, и всё равно в непонятках. Можно как то в более доступном пошаговом варианте для чайников...Я говорю как потребитель, а не как " вы - магистр". Мне кажется что многие пользователи не такие продвинутые, хотя это наши проблемы отчасти.

Не, вы, если что, спрашивайте или так и говорите, что не понятно.
Вот. Дополнил и оформил первое сообщение более наглядно.

Но тут, всё таки, небольшие знания как работает HTTP (и что есть такие заголовки) и хоть немного понимать код, всё-таки, нужно. Т.е. совсем в этом не разбирающимся людям можно даже не пытаться. Ну, а если есть желание разобраться, то задавайте вопросы.

Sony Bravia KDL-32CX523

4

Re: Авторизация на сайтах

WendyH, доброго времени суток
просьба прикрепить эту тему т.к. в ней есть много полезных вещей.

LG 42LA644V/Philips 32PFL3605/60

5

Re: Авторизация на сайтах

Даладна, пора уже наверно отдельный цитатник издавать  :)

LG 32LA615V

6 (2017.11.05 19:53:33 отредактировано Oompaloomp)

Re: Авторизация на сайтах

WendyH, доброго времени суток
прошу помощи с charles 4.2-win32
Не знаете как поправить кракозябры запросах:

+ открыть спойлер

http://i3.imageban.ru/out/2017/11/05/1cb54f5204e238f23e44b7bc25a054b7.png

LG 42LA644V/Philips 32PFL3605/60

7

Re: Авторизация на сайтах

Oompaloomp пишет:

WendyH, доброго времени суток
прошу помощи с charles 4.2-win32
Не знаете как поправить кракозябры запросах:

Это не кракозябры. Это зашифрованный траффик. Протокол https.
Расшифровать можно только если настройки сайта на сервере не сильно ревнуют к самопальному сертификату с неподдвержаемым рутовыми центрами сертификации.

1) Нажимаем "Help" - "Install Charles CA SSL certificate..."
2) "Proxy" -> "Proxy settings" -> вкладка "SSL"
3) Нажимаем Add и вписываем доменное имя сайта (например, filmix.me) и порт 443, нажимаем ОК.

После этого можно в браузере переходить на сайт. Браузер может ругнуться, что сертификат не подтверждён, произошла подмена, караул. В этом случае, нажимаем "Подробно" -> "Всё равно перейти" или как-то так.
Если всё получилось, то вы стали практически хакером с атакой "человек-по-середине", вставив свой сертификат для расшифровки в общение между сайтом и браузером. )

Если пользуетесь хромом, то в некоторых случаях при использовании HSTS на сайтах (типа как здесь на форумах) он может не дать вам перейти на него вообще.
Тогда можно попробовать в Firefox при такой ругани добавить сайт в исключения на такие ошибки.

Sony Bravia KDL-32CX523

8

Re: Авторизация на сайтах

WendyH, спасибо за помощь
заработало.

LG 42LA644V/Philips 32PFL3605/60