уважаемые посетители блога, если Вам понравилась, то, пожалуйста, помогите автору с лечением. Подробности тут.

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

Цель сегодняшней работы: авторизоваться на сайте по https-протоколу с использованием библиотеки Synapse.

Суть проблемы: не проходит авторизация при использовании метода HTTPMethod(), не устанавливаются новые cookies и т.д.

Целевой сайт:  https://partner.r01.ru

Чтобы пост был полезен и интересен не только одному человеку, то позволю себе рассмотреть всю работы подробно.

1. Изучаем процесс авторизации

Первое, что я сделал — зарегистрировался на «проблемном» сайте и изучил подробно все запросы и заголовки запросов при авторизации.

В качестве просмотрщика заголовков использовался плагин к FireFox «Live Headers».

Заголовок сообщения при авторизации методом POST выглядит следующим образом:

Ответ сервера при успешной авторизации:

При неудачной авторизации редирект (302) не происходит, несмотря на то, что cookies всё равно устанавливаются.

Таким образом, для того, чтобы авторизоваться на сайте с использованием Synapse нам необходимо:

  1. Сформировать и отправить по протоколу https запрос
  2. Определить в заголовке ответного сообщения либо редирект и перейти на новый адрес (при успешной регистрации) либо получить код 200 и констатировать провал «операции».

2. Век живи — век учись

Первое, с чего я начал работу с Synapse — это отправил на сервер get-запрос с целью получить необходимые cookies, предположив, что авторизация на сайте будет схожа по принципу со способом из этого поста. А кукисы-то и не пришли, несмотря на то, что вроде бы никаких видимых ошибок в работе Synapse замечено не было.

Порывшись немного по Интернету, нашел небольшое примечания к работе с https-протоколом в Synapse. Дело в том, что

для правильной работы с https помимо модуля httpsend, необходимо использовать также модуль ssl_openssl из той же библиотеки.

Вот так вот. Теперь попробуем пройти весь путь авторизации. Открываем Delphi и создаем новый проект. У меня на главной форме размещены следующие элементы:

  • 2 edit’а для воода логина и пароля;
  • button с ничего не говорящим названием «Login»
  • 2 Memo — в первый будем выводить все полученные кукисы и заголовки, а во второй — содержимое полученного документа после успешной авторизации.

Внешний вид программы у меня получился такой:

Может видок и неказистый, но, для тестов вполне достаточно.

Вначале приведу уже рабочий код обработчик события onClick кнопки — в нем мы отправляем запрос и проверяем прошла ли авторизация:

procedure TForm5.Button1Click(Sender: TObject);
 
function GetLocation(const headers:TStringList):string;
var i:integer;
begin
  for I := 0 to headers.Count - 1 do
    if pos('Location: ',headers[i])>0 then
        begin
          Result:=copy(headers[i],10,length(headers[i])-9);
          break;
        end;
end;
 
var stream: TStringStream;
httpsend: THTTPSend;
begin
  Memo1.Clear;
  Memo2.Clear;
  stream:=TStringStream.Create('');
  stream.WriteString('wizard_domain2=&auid=&htid=&;action=1&login='+Edit1.Text+'&passwd='+Edit2.Text);
  httpsend:=THTTPSend.Create;
  httpsend.MimeType:='application/x-www-form-urlencoded';
  httpsend.Document.LoadFromStream(stream);
  if httpsend.HTTPMethod('post','https://partner.r01.ru/?' ) then
    begin
      Memo2.Lines.Add('Отправка запроса. Ответ сервера');
      Memo2.Lines.Add('-----Cokies-----');
      Memo2.Lines.add(httpsend.Cookies.Text);
      Memo2.Lines.Add('-----Headers-----');
      Memo2.Lines.add(httpsend.Headers.Text);
      if httpsend.ResultCode=302 then
        begin
           if pos('/AB/about_abonent.khtml',GetLocation(httpsend.Headers))>0 then
             begin
               httpsend.Document.Clear;
               httpsend.Headers.Clear;
               httpsend.HTTPMethod('get','https://partner.r01.ru/AB/about_abonent.khtml');
               httpsend.Document.SaveToStream(stream);
               Memo1.Lines.Add(KOI8R2ANSI(stream.DataString));
             end
          else
            Memo1.Lines.Add('Авторизация не удалась')
         end
       else
         Memo1.Lines.Add('Авторизация не удалась')
    end;
end;

Обратите внимание на часть кода:

[...]
if pos('/AB/about_abonent.khtml',GetLocation(httpsend.Headers))>0 then
  begin
    httpsend.Document.Clear;
    httpsend.Headers.Clear;
    httpsend.HTTPMethod('get','https://partner.r01.ru/AB/about_abonent.khtml');
[...]

Всё дело в том, что при успешной авторизации редирект приходит на адрес:

/AB/about_abonent.khtml?regbase2_id=da…

и сколько раз я не пробовал получить документ по этому адресу — ничего не получилось. Поэтому поступил так «топорно» и всё сработало.

В ответном сообщении был получен документ содержащий html-код для страницы личного кабинета.

Ещё один «нестандартный» момент при работе с этим сайтом заключается в том, что страница приходит9 в кодировке KOI8-R и, следовательно, без дополнительной обработки текста мы получим вместо русского текста «кракозябры».

Для того, чтобы избежать неприятных моментов с русскими буквами я использовал вот такую нехитрую функции перекодирования текста из KOI8-R в ANSI:

function KOI8R2ANSI(S: string): string;
var
Ansi_CODE, KOI8_CODE: string;
i: integer;
begin
KOI8_CODE := 'бвчздецъйклмнопртуфхжигюыэящшьасБВЧЗДЕЦЪЙКЛМНОПРТУФХЖИГЮЫЭЯЩШЬАС—Ј';
ANSI_CODE := 'АБВГДЕЖЗИЙКЛМНОПРСТУФХЦЧШЩЪЫЬЭЮЯабвгдежзийклмнопрстуфхцчшщъыьэюя№ё';
Result := S;
for i := 1 to Length(Result) do
  if Pos(Result[i], KOI8_CODE) > 0 then
    Result[i] := ANSI_CODE[Pos(Result[i], KOI8_CODE)];
end;

Вот, пожалуй, и все, что касается авторизации на сайте https://partner.r01.ru.

P.S. Уважаемая,dkdk, надеюсь я не слишком опоздал с помощью и приведенный выше код Вам помог ;)

0 0 голоса
Рейтинг статьи
уважаемые посетители блога, если Вам понравилась, то, пожалуйста, помогите автору с лечением. Подробности тут.
Подписаться
Уведомить о
94 Комментарий
Межтекстовые Отзывы
Посмотреть все комментарии
Dimrix
Dimrix
10/08/2012 18:21

У меня проблема с Post’ом. Вообщем я по очереди отправляю 2 Post’а:
1. httpsend.HTTPMethod(‘post’,’https://assa.intertelecom.ua/ru/login’ ) который возвращает httpsend.ResultCode=301 как признак успешной авторизации на сайте
2. httpsend.HTTPMethod(‘post’,’https://assa.intertelecom.ua/ru/config’ )который возвращает httpsend.ResultCode=200 а должен 301. 200 я получаю при ‘get’ — почему вылазит у меня 200 и на пост? Или нельзя отправлять 2 поста?

Dimrix
Dimrix
10/08/2012 18:46

Блин 3 часа пробился — не мог понять в чем проблема, решил у гуру спросить. Только написал сюда и нашёл ошибку. Пишу, да бы другие время не тратили за зря. Вообщем в начале объявляем
httpsend.MimeType:=’application/x-www-form-urlencoded’;
И входе считывания данных этот параметр поменялся. В следствии чего, при отправке запроса (‘post’) у меня он обрабатывался как get. Просмотрел все переменные в итоге и выявил, что httpsend.MimeType поменял значение. Перед 2ым запросам опять поставил нужное — пост обработался успешно.
ВООБЩЕМ: перед каждым постом как минимум перепроверяйте значение переменной httpsend.MimeType и будет Вам счастье

Sergey
Sergey
18/10/2012 17:04

Здравствуйте. Может быть кто знает, почему при подключении модуля ssl_openssl после запуска приложения главное окно появляется спустя ~2 секунды?

trackback
Итоги 2012 года на WebDelphi.ru | Delphi в Internet
28/12/2012 16:03

[…] Synapse. Авторизация на сайте. Работа с HTTPS. […]

stanislav
stanislav
05/01/2013 23:59

Хм, у меня при добавлении модуля ssl_openssl тоже подвисает программа. Так и должно быть? Как избавится от подвисания? Это ведь не дело…
С Уважением.

Vasja
Vasja
12/01/2013 21:36

Спасибо. Замечательная статья.
Только я использовал не FireFox для просмотра (чего-то оно не пошло у меня), а встроенную возможность Opera, которая вызывается по Ctrl+Shift+I. И там закладка Сеть, а в ней Журнал сети.
Ну, и ещё, как новичок, не сразу въехал, что нужно в каталог программы подложить 2 библиотеки от пакета OpenSSL — это libeay32.dll и ssleay32.dll. Потому что исключение в synapse не генерируется — не сразу понял, почему httpsend.HTTPMethod() возвращает False. И ещё у меня получилось, что вместо about_abonent с сайта возвращается текст desktop (может уже на сайте поменяли чего…). Но а так работает.

SomeBody
SomeBody
17/02/2013 02:15

if pos('/AB/about_abonent.khtml',GetLocation(httpsend.Headers))>0 then
«>» should be «>» =)

m-a
m-a
29/04/2014 17:10

Большое спасибо за акцентирование на куске кода:

httpsend.Document.Clear;
httpsend.Headers.Clear;

так бы и не обратил внимания. Делал авторизацию в Яндекс.Паспорт, там три редиректа подряд. Что только ни пробовал, при первом же переходе по новому location сервер выдавал код 400 «Bad request». Эти две строчки решили проблему.

Сергей
Сергей
07/09/2014 19:47

Есть неувязочка. Дело в том, что если пароль будет содержать символы «%» и прочие web-штучки, то при использовании
httpsend.MimeType:=’application/x-www-form-urlencoded’;
эти символы будут либо пропадать, либо заменяться. Получается, что авторизация не пройдет.
Как решить эту проблему?

Сергей
Сергей
07/09/2014 19:54
Ответить на  Сергей

Уже нашел решение :) Нужно предварительно обработать нужную строку методом EncodeURLElement из модуля SynaCode.

Dimrix
Dimrix
09/12/2014 19:01

У меня нет ответа при запуске приложения под 64бит: if httpsend.HTTPMethod(‘post’,’https://partner.r01.ru/?’ ) then возвращает False как победить?

Сергей
Сергей
29/05/2015 21:36

В чем может быть причина, что в Windows 8.1 не выполняется запрос httpsend.HTTPMethod(‘post’,’https://partner.r01.ru/?’ ); ResultCode равен 500, а в windows 7 работает.

Александр
Александр
23/07/2015 21:51
Ответить на  Сергей

Сергей, столкнулся с такой же проблемой что и вы. Оказалось что я не переносил на тестовые машины 2 dll — библиотеки необходимые для работы программы с open-ssl(libssl32.dll, libeay32.dll). На Windows 7 действительно такой проблемы не было.

Сергей
Сергей
24/07/2015 12:47
Ответить на  Александр

Александр благодарю за ответ, так есть, просто у меня на компе работало без проблем, что эта библиотека уже имелась в системной папке, занесенная делфи или еще кем, также и у других пользователей у кого работало, у кого нет по этой же причине, windows 8.1 в данном случае не грешит)

Сергей Гурин
15/11/2016 06:36

Пытаюсь получить страницу на этом сайте https://pw.mail.ru/account.php
Нормально получаю и могу получить много раз
После регистрации тут https://authdl.mail.ru/sz.php?hint=Auth
я страницу https://pw.mail.ru/account.php получить уже не могу
ResultCode=500
HTTPSend.Sock.LastErrorDesc = error:140A90F1:lib(20):func(169):reason(241)
пока не перегружу программу

Компонент пересоздаю, куки чищу — ничего не помогает
Не подскажите в чем проблема?

#gennick
#gennick
23/04/2018 09:10