Модераторы: Snowy, Poseidon, MetalFan

Поиск:

Ответ в темуСоздание новой темы Создание опроса
> Статья : Авторизация и аутентификация на сайтах, через WinInet 
:(
    Опции темы
 
Помогла ли вам моя статья?
Да, статья супер :-) [ 3 ]  [42.86%]
Во многом помогла :P [ 1 ]  [14.29%]
Половину не знал, половину знал ) [ 0 ]  [0.00%]
Во многом, этот материал я уже знаю [ 2 ]  [28.57%]
Мало, что нового узнал:/ [ 1 ]  [14.29%]
Нет, не в чем, я и так все знал:( [ 0 ]  [0.00%]
Всего проголосовавших: 7
В этом опросе возможен один вариант ответа
Гости не могут голосовать 
Brausman
Дата 22.10.2009, 19:24 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 26
Регистрация: 1.4.2009

Репутация: 2
Всего: 1



Начнем по порядку, так как я пишу свою первую статью, не бейте сильно за нее.
В данной статье буду рассмотрены вопросы :
-Авторизации на любом из сайтов(http и https с подтвержденными сертификатами), через ввод логин/пароля в браузере, 2 способами;
-Аутентификация, программное подставление сертификата в запрос к серверу,если он его требует,ручная аутентификация с помощью браузера показана ниже.
user posted image



-Аутентификация с авторизацией,через системное окно авторизации windows , которое показано ниже
 user posted image


1. Начнем с теории, ниже буду приведены ссылки на ресурсы, по которым не сведущий в WinInet человек сможет разобраться, в его основах:
http://www.delphisources.ru/pages/faq/base..._functions.html - данная статья рассказывает об основных функция Win 32 API для работы с интернетом
http://kodu.neti.ee/~juri4/vfpplus/inet_11_ru.htm - данная статья предназначена для программистов под VisualFox Pro, но полезности ее не умоляет, в ней описаны все возможные флаги для WIn 32 API функций работы с интернетом описанных ссылкой выше
http://programmersforum.ru/showthread.php?t=38803 - в данной статье рассказано как анализировать html-код страницы перед написанием запроса авторизации.

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

Автор предупреждает, что не будет вступать в споры по поводу оптимизации кода, данная статья не про это

2.  И так нам понадобится CodeGear Rad Studio 2009 и сниффер(программа для отслеживания запросов/ответов между клиентом и сервером) HTTP Analyzer.
Сначало опишем нужные нам функции, которые потом буду использоваться для наших нужд.

а) В функцию 
Код
InternetConnect
, под параметром 
Код
lpszServerName: PChar
 передается имя сервера, т.е. 
для http://www.delphisources.ru/pages/faq/base/inet_win32_api_functions.html имя сервера будет www.delphisources.ru,следовательно из полного url нам нужно его вытащить, для этого предназначена простенькая функция:
Код

function GetHostName(url : string) : string;
begin
  result := '';
  if pos('https://',url) > 0 then
    begin
      delete(url,1,length('https://'));
      SetLength(url,pos('/',url) - 1);
      result := url;
    end
  else
    if pos('http://',url) > 0 then
      begin
        delete(url,1,length('http://'));
        SetLength(url,pos('/',url) - 1);
        result := url;
      end;
end;


б) Идем дальше)), в функцию 
Код
HttpOpenRequest
 передается параметр
Код
lpszObjectName
 - он же скрипт, также берется из полного url, из
http://www.delphisources.ru/pages/faq/base/inet_win32_api_functions.html  скрипт будет 
pages/faq/base/inet_win32_api_functions.html ,для его вытаскивания служит следующая функция :
Код

function GetScriptName( url,hostname : string) : string;
begin
  result := '';
  delete(url,1,pos(hostname,url) + length(hostname));
  result := url;
end;


в) Теперь напишем функцию, которая в зависимости от протокола безопасности (http или https), будет возвращать нам нужные флаги для последующей их подстановки в  
Код
InternetConnect и HttpOpenReques
, напишем ее:
Код

procedure SetFlags(url : string; out Flags_connection,Flags_Request : Cardinal);
begin
  //Оприделяем на https или http
  if pos('https',url) > 0 then
    begin
      Flags_connection := INTERNET_DEFAULT_HTTPS_PORT;
      Flags_Request := INTERNET_FLAG_RELOAD or INTERNET_FLAG_IGNORE_CERT_CN_INVALID or INTERNET_FLAG_NO_CACHE_WRITE or INTERNET_FLAG_SECURE or INTERNET_FLAG_PRAGMA_NOCACHE or INTERNET_FLAG_KEEP_CONNECTION;
    end
  else
    begin
      Flags_connection := INTERNET_DEFAULT_HTTP_PORT;
      Flags_Request := INTERNET_FLAG_RELOAD or INTERNET_FLAG_IGNORE_CERT_CN_INVALID or INTERNET_FLAG_NO_CACHE_WRITE or INTERNET_FLAG_PRAGMA_NOCACHE or INTERNET_FLAG_KEEP_CONNECTION;
    end;
end;


Какой флаг, что означает вы узнаете перейдя по данной мной выше ссылки.

г) Так как нам ответ от сервера будет приходить в виде данных, то мы должны знать скольза за один раз передается нам данных от сервера, для этого служит следующая функция:
Код

function DataAvailable(hRequest: pointer; out Size : cardinal): boolean;
begin
  result := wininet.InternetQueryDataAvailable(hRequest, Size, 0, 0);
end;



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

После запуска на отлавливание запросов/ответов, он будет фиксировать всю вашу активность в сети, т.е. работу вашего браузера,аси,торрент-трекера.
Внизу имеются вкладки, нам интересны:
-Header - двойное окно показывающая запрос от программы(например браузера IE) - слева и ответ сервера - справа;
-Response Content - html-текст который возвращает нам сервер на наш запрос;
-Post Data - отображает данные передаваемые наше программой при вызове метода Post(в данном виде передается подавляющее число логин/паролей и сопутствующей информации при авторизации через браузер);
-Query String- отображает альтернативный(методу Post Data) метод передачи данных об авторизации, через окно браузера;
-Raw Stream - окно паказывающая полный запрос программы к серверу, полезен при отладке.

Теперь переходим к авторизации и аутентификации.

3.  Авторизация на сайтах методом добавления в url , списка данных необходимых для авторизации, данный способ применим на подавляющем кол-ве серверов, исключения не сертифицированные https серверы, ну и еще какие-нибудь :P.

Добавление происходит,через специальный разделитель - ? добавляемый в конец нашего url, если он уже там есть, мы ни чего не добавляем.
В данном примере мы будем авторизовываться на сайте "в контакте", так как я находил в интернете не один пост на счет етого.
Теперь добавим разделитель и наш url будет выглядеть так:
http://vkontakte.ru/login.php?
Теперь после разделителя нужно добавить данные для авторизации, для этого я зарегистрировался на сайте, вот параметры:
Код

Логин : [email protected]
Пароль : 1234567

Но, что же подставлять, какие данные, в стать приведенной выше описывался метод, как узнать что передается, но у нас же есть сниффер предоставим все ему.
Для этого в форме регистрации на сайте в контакте вбейте приведенные выше данные и нажмите "вход"
В сниффере сразу отобразятся все запросы/ответы межу серваком и браузером.
В столбце Method - написан метод запроса к серверу(в данном примере Post), значит будем использовать его, потом url к  которому пошел запрос(наш http://vkontakte.ru/login.php?), так как метод был Post, то все данные передаваемые с запросом находятся во вкладке Post Data, но перейдя на нее мы ни чего не увидим.Почему? Все дело в том что данные передаются по url обозначенному в методе action если разбирать html-код страницы, ну тогда глянем, и вот что мы имеем:
Код

form method="post" - метод передачи
action="http://login.vk.com/" - url запроса к серверу

Следовательно данные передавались с ним, нажав на данный url и перейдя во вкладку Post Data, мы увидим нужные нам данные которые пересылаются вместе с запросом, теперьо нажимаем правой кнопкой мыши на один из параметров и в сплявающем меню нажмем "View Row Data", откроется блокнот с представленными нам в нужном виде данными, они выглядят так:
Код

act=login&success_url=&fail_url=&try_to_login=1&to=&vk=&[email protected]&pass=1234567&expire=

Теперь добавляем,это просто в конец нашего первоначально url(по  хорошему метод передачи и url запроса смотрится в коде страницы), но мы будем переходить по http://vkontakte.ru/login.php, а не описанному в action="http://login.vk.com/", просто потому, что и так проходит авторизация, но правильно брать url из action.
И финальный вид нашего url будет:
Код

http://vkontakte.ru/login.php?act=login&success_url=&fail_url=&try_to_login=1&to=&vk=&[email protected]&pass=1234567&expire=


Теперь напишу функцию которая авторизуется по данному url с данными:
Код

function GETURL2HTML(url : string;param : Ansistring ;method : string) : AnsiSTRING;//Получение страницы по url
var
  FHost,FScript : string;
  hInternet,hConnect,hRequest : Pointer;
  dwBytesRead,I,L : Cardinal;
  Flags_connection,Flags_Request : Cardinal;
begin
  result := '';

  fHost := GetHostName(url);
  fScript := GetScriptName(url,fHost);
  if Param <> '' then
    if fScript[Length(fScript)] = '?' then
      fScript := fScript + param
    else
      fScript := fScript + '?' + param;

  //Устанавливаем флаги
  SetFlags(url,Flags_connection,Flags_Request);
  //Инициализируем WinInet
  hInternet := InternetOpen(PChar(Application.ExeName),INTERNET_OPEN_TYPE_PRECONFIG,Nil,Nil,0);
  if Assigned(hInternet) then
    begin
      //Открываем сессию
      hConnect := InternetConnect(hInternet,PChar(FHost),Flags_connection,nil,nil,INTERNET_SERVICE_HTTP,0,1);
      if Assigned(hConnect) then
        begin
          //Формируем запрос
          hRequest := HttpOpenRequest(hConnect,PChar(uppercase(method)),PChar(fScript),HTTP_VERSION,nil,Nil,Flags_Request,1);
          if Assigned(hRequest) then
            begin
              //Отправляем запрос
              I := 1;
              if HttpSendRequest(hRequest,nil,0,nil,0) then
                begin
                  repeat
                  DataAvailable(hRequest, L);//Получаем кол-во принимаемых данных
                  if L = 0 then break;
                  SetLength(result,L + I);
                  if InternetReadFile(hRequest,@result[I],sizeof(L),dwBytesRead) then//Получаем данные с сервера
                  else break;

                  inc(I,dwBytesRead);
                  until dwBytesRead = 0;
                  result[I] := #0;
                end;
            end;
            InternetCloseHandle(hRequest);
        end;
        InternetCloseHandle(hConnect);
    end;
    InternetCloseHandle(hInternet);
end;


Здесь мы получаем html-код страницы,если мы авторизовались,
FHost - имя сервера;fScript - скрипт выполняемый при подключении(т.е. переход на страницу пользователяесли передаваеммые данные верня).
Данные метод действует и для http и для htpps.

4.  авторизация 2 методом, когда серверы требуют передавать данные авторизации не через конец url, а через "Post Data"- опции запроса. 
Вид представления жанных тот же ,что и в предыдущем примере:
Код

act=login&success_url=&fail_url=&try_to_login=1&to=&vk=&[email protected]&pass=1234567&expire=


Но теперь мы их будем передавать через опции запроса 
Код
HttpSendRequest
,
также отдельно стои сказать что вы должны передать в виде системной опции через туже функцию размер строки данных, она будет выглядить так:
Код

Type_Acess := 'Content-Type: application/x-www-form-urlencoded' + #13#10 +
                    'Content-Length:'+ inttostr(length(param)) ;

где 'Content-Length:'+ inttostr(length(param)) - и есть описание размерности строки.
А сами параметры передаются через 
Код
HttpSendRequest
, в виде :
Код

HttpSendRequest(hRequest,PChar(Type_Acess),length(Type_Acess),PChar(param),length(param))


ГЛАВНОЕ ЧТО НЕ ЗАБУДЬТЕ ПЕРЕМЕННАЯ PARAM ДОЛЖНА БЫТЬ ТИПА ANSISTRING ИЛИ utf8STRING, ТАК КАК HttpSendRequest - ПЕРЕДАЕТ PAnsiChar - из-за чего будут проблемы с кодировкой если использовать обычную string, так по крайней мере в Delphi 2009.

Привожу весь листинг функции авторизации :
Код

function GETURL2HTML(url : string;param : Ansistring ;method : string) : AnsiSTRING;//Получение страницы по url
var
  FHost,FScript : string;
  hInternet,hConnect,hRequest : Pointer;
  dwBytesRead,I,L : Cardinal;
  Flags_connection,Flags_Request : Cardinal;
  Type_Acess : string;
begin
  result := '';

  Type_Acess := 'Content-Type: application/x-www-form-urlencoded' + #13#10 +
                    'Content-Length:'+ inttostr(length(param)) ;
  fHost := GetHostName(url);
  fScript := GetScriptName(url,fHost);

  //Устанавливаем флаги
  SetFlags(url,Flags_connection,Flags_Request);
  //Инициализируем WinInet
  hInternet := InternetOpen(PChar(Application.ExeName),INTERNET_OPEN_TYPE_PRECONFIG,Nil,Nil,0);
  if Assigned(hInternet) then
    begin
      //Открываем сессию
      hConnect := InternetConnect(hInternet,PChar(FHost),Flags_connection,nil,nil,INTERNET_SERVICE_HTTP,0,1);
      if Assigned(hConnect) then
        begin
          //Формируем запрос
          hRequest := HttpOpenRequest(hConnect,PChar(uppercase(method)),PChar(fScript),HTTP_VERSION,nil,Nil,Flags_Request,1);
          if Assigned(hRequest) then
            begin
              //Отправляем запрос
              I := 1;
              if HttpSendRequest(hRequest,PChar(Type_Acess),length(Type_Acess),PChar(param),length(param))  then
                begin
                  repeat
                  DataAvailable(hRequest, L);//Получаем кол-во принимаемых данных
                  if L = 0 then break;
                  SetLength(result,L + I);
                  if InternetReadFile(hRequest,@result[I],sizeof(L),dwBytesRead) then//Получаем данные с сервера
                  else break;

                  inc(I,dwBytesRead);
                  until dwBytesRead = 0;
                  result[I] := #0;
                end;
            end;
            InternetCloseHandle(hRequest);
        end;
        InternetCloseHandle(hConnect);
    end;
    InternetCloseHandle(hInternet);
end;


Это сообщение отредактировал(а) THandle - 25.10.2009, 11:04
PM MAIL   Вверх
Brausman
Дата 22.10.2009, 19:39 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 26
Регистрация: 1.4.2009

Репутация: 2
Всего: 1



5.  Теперь давайте чучуть отклонимся от темы и рассмотрим такой пример, что после авторизации, редирект(перенаправление) не происходит, это случется в основном если приходит к нам скрипт и внутри него ссылка куда переходить, по такому методу идет авторизация на yahoo.com.
Вот логин и пароль для тестирования:
Логин: [email protected]
Пароль : 1234567

Делаем, что и в предыдущем примере, сначала через браузер, потом исследуем все в сниффере, мы будем передавать данные как и в первом случае через дописывания в url.
Привожу листинг функции:
Код

function GETURL2HTML(url : string;param : Ansistring ;method : string) : AnsiSTRING;//Получение страницы по url
label 10;
var
  FHost,FScript : string;
  hInternet,hConnect,hRequest : Pointer;
  dwBytesRead,I,L : Cardinal;
  Flags_connection,Flags_Request : Cardinal;
  Type_Acess : string;
begin
  result := '';

  fHost := GetHostName(url);
  fScript := GetScriptName(url,fHost);
  if Param <> '' then
    if fScript[Length(fScript)] = '?' then
      fScript := fScript + param
    else
      fScript := fScript + '?' + param;

  //Устанавливаем флаги
  SetFlags(url,Flags_connection,Flags_Request);
  //Инициализируем WinInet
  hInternet := InternetOpen(PChar(Application.ExeName),INTERNET_OPEN_TYPE_PRECONFIG,Nil,Nil,0);
  if Assigned(hInternet) then
    begin
      //Открываем сессию
      hConnect := InternetConnect(hInternet,PChar(FHost),Flags_connection,nil,nil,INTERNET_SERVICE_HTTP,0,1);
      if Assigned(hConnect) then
        begin
          //Формируем запрос
          hRequest := HttpOpenRequest(hConnect,PChar(uppercase(method)),PChar(fScript),HTTP_VERSION,nil,Nil,Flags_Request,1);
          if Assigned(hRequest) then
            begin
10:
              //Отправляем запрос
              I := 1;
              if HttpSendRequest(hRequest,{PChar(Type_Acess)}nil,{length(Type_Acess)}0,{PChar(param)}nil,{length(param)}0)  then
                begin
                  repeat
                  DataAvailable(hRequest, L);//Получаем кол-во принимаемых данных
                  if L = 0 then break;
                  SetLength(result,L + I);
                  if InternetReadFile(hRequest,@result[I],sizeof(L),dwBytesRead) then//Получаем данные с сервера
                  else break;

                  inc(I,dwBytesRead);
                  until dwBytesRead = 0;
                  result[I] := #0;
                end;
            end;
            InternetCloseHandle(hRequest);
        end;

        if pos('window.location.replace("',result) > 0 then
          begin
            url := 'http://ru.yahoo.com/'; //Ест я сам тут кинул по идее можно прям от туда тащить из результа
            fHost := GetHostName(url);
            fScript := GetScriptName(url,fHost);
            //Устанавливаем флаги
            SetFlags(url,Flags_connection,Flags_Request);
            //Если не через редирект то методом гет заходим
            hConnect := InternetConnect(hInternet,PChar(fHost),Flags_connection,nil,nil,INTERNET_SERVICE_HTTP,0,1);
            if Assigned(hConnect) then
              begin
                //Формируем запрос
                hRequest := HttpOpenRequest(hConnect,PChar(uppercase('GET')),PChar(fScript),HTTP_VERSION,nil,Nil,Flags_Request,1);
                if Assigned(hRequest) then
                  begin
                    result := '';
                    goto 10;
                  end;
              end;
          end;
        InternetCloseHandle(hConnect);
    end;
    InternetCloseHandle(hInternet);
end;

Теперь поясняю после запроса метода POST, мы получает ответ от сервера в виде:
Код

<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
<script language="JavaScript">
<!--
window.location.replace("http://my.yahoo.com");
// -->
</script>
<meta http-equiv="Refresh" content="0; url=http://my.yahoo.com">
</head>
<body>
If you are seeing this page, your browser settings prevent you
from automatically redirecting to a new URL.
<p>
Please <a href="http://my.yahoo.com">click here</a> to continue.
</body>
</html>


Так как мы не указывали в параметрах запроса что мы из России:
Код

Referer:https://login.yahoo.com/config/login_verify2?.src=www&.intl=ru&.done=http://ru.yahoo.com/
Accept-Language:ru

То нам вернули ссылку на англоязычный сервис 
Код
http://my.yahoo.com
, но главное вернули значит мы все сделаи правильно и потом методом GET - основной метод переходов, переходим на наш ru.yahoo.com)))? вот в принципе и все на этот счет, идем дальше.


Примечание:

У серверов с не подтвержденным сертификатом(когда браузер ругается и предлогает не заходить на данный сервер), имеется проблема, если не получается к нему присоединится 12003 - ошибка, то есть два выхода:
1) У некоторых серверов есть семитричные url, только на обычном http, т.е. можно по тупому взять и вместо https//:блаблабла написать http//: и авторизоваться через него(у моего провайдера нета так у меня и получилось)
2)И более верный просто вместо имени подставиь IP сервера,его можно узнать когда сделаете запрос через браузер к этому серверу и в сниффере на вкладке "Raw Stream" - над текстом будет его IP.

6.  Ну и наконец мы подошли до аутетификации я решил взять и совместить 2 и 3 вопос статьи, так как отличий я не вижу, а коментарии дам одни.

Щас разберем пример, когда сервер по https(хотя без разницы http или https), требует сертификат и также авторизацию через системное окно Windows и к тому сертификат не проверенный(это бывает когда создатели сертификата не хотят платить Microsoft за то чтоб он зарегистрировал их сертификат в базе данных сертификатов Microsoft). К сожалению тестовый пример я дать не могу так как это конфиденциальная информация предприятия, так что поверьте мне наслово:P.


Как говорилось выше в примечании, будем использовать IP а не имя из url'а.

Теперь всьтает вопрос как программно добавить сертификат в запрос, для этого надо получить указатель на него в хранилище сертификатов вашего комп. И вот как это делается.
Вы не сможите найти сертификат нужный вам без его идентификационного имени в хранилище сертификатов( по буржуйски Subject),для этого я прилогаю к статье небольшой проект который в тексстовом формате может выводит все сертификаты которые имеются в хранилищах сертификатов вашего компа.Я сказал хранилищах? Да я не оговорился их не 1, а 3, а с помощью нас программистов их может быть 4, и у них есть свои уникальные названия :
//MY - для хранения сертификатов отдельного пользователя
//СА - от Certification Authority - для хранения сертификатов центров сертификации
//ROOT - для хранения корневых сертификатов
//А также тан называемое хранилище колекции сертификатов создаваемое исключительно программистом под себя, как назовете так и будет.

Теперь вам необходимо подключить к проекту .pas - файл для работы с сертификатами - wcrypt2.pas, я его также приложил к статье отдельно, стоит упомянуть, что он не до конца доработат, многих констант ошибок и некоторых функций для работы с сертификатами там попросту нет, что мне надо было я дописал, так что я предупредил.

Также отмечу, что пока вы не авторизуетесь на сервере через браузер, сертификат не добавится не в одно из хранилищ и вы его попросту не найдете, а метод через путь до сертификата на компе, когда он лежит файлом я рассматривать не буду. По умолчанию данные сертификаты добавляются в MY хранилище


Теперь приведу функцию для получения указателя на нужный нам сертификат:
Код

//Функция нахождения сертификата
function FindCertificate( Subject : string; CertStore : string ) : PCCERT_CONTEXT;
var
    prov: HCRYPTPROV;
    store: HCERTSTORE;
    stor: PChar;
    subj: PWideChar;
    encType : DWORD;
    error : string;
begin

result := nil;

CertStore := uppercase(CertStore);//переводим в верхний регистр

encType := PKCS_7_ASN_ENCODING or X509_ASN_ENCODING;//виды шифрования

//Проверяем криптопровайдера на всекий случай можно и без этого
if not CryptAcquireContext(@prov, nil, nil, PROV_RSA_FULL, 0)
then
    begin
      case int64(GetLastError) of
        ERROR_INVALID_PARAMETER: error := 'ERROR_INVALID_PARAMETER';
        ERROR_NOT_ENOUGH_MEMORY: error := 'ERROR_NOT_ENOUGH_MEMORY';
        NTE_BAD_FLAGS: error := 'NTE_BAD_FLAGS';
        NTE_BAD_KEYSET: error := 'NTE_BAD_KEYSET';
        NTE_BAD_KEYSET_PARAM: error := 'NTE_BAD_KEYSET_PARAM';
        NTE_BAD_PROV_TYPE: error := 'NTE_BAD_PROV_TYPE';
        NTE_BAD_SIGNATURE: error := 'NTE_BAD_SIGNATURE';
        NTE_EXISTS: error := 'NTE_EXISTS';
        NTE_KEYSET_ENTRY_BAD: error := 'NTE_KEYSET_ENTRY_BAD';
        NTE_KEYSET_NOT_DEF: error := 'NTE_KEYSET_NOT_DEF';
        NTE_NO_MEMORY: error := 'NTE_NO_MEMORY';
        NTE_PROV_DLL_NOT_FOUND: error := 'NTE_PROV_DLL_NOT_FOUND';
        NTE_PROV_TYPE_ENTRY_BAD: error := 'NTE_PROV_TYPE_ENTRY_BAD';
        NTE_PROV_TYPE_NO_MATCH: error := 'NTE_PROV_TYPE_NO_MATCH';
        NTE_PROV_TYPE_NOT_DEF: error := 'NTE_PROV_TYPE_NOT_DEF';
        NTE_PROVIDER_DLL_FAIL: error := 'NTE_PROVIDER_DLL_FAIL';
        NTE_SIGNATURE_FILE_BAD: error := 'NTE_SIGNATURE_FILE_BAD';
      else error := 'Не известная ошибка';
      end;
      MessageDlg('Ошибка создания контейнера: ' + error, mtError, [mbOK], 0);
      exit;
    end;

stor := StrAlloc(length(CertStore) + 1);//выделяем память под строку
StrPCopy(stor, CertStore);//копируем
store := CertOpenSystemStore(prov, stor);//Открываем хранилище сертификатов
StrDispose(stor);//Освобождаем память
if store = nil then
   begin
    MessageDlg('Не можем открыть хранилище сертификатов', mtError, [mbOK], 0);
    CertCloseStore(store, 0);//освобождаем память
    CryptReleaseContext(prov, 0);//освобождаем память
    result := nil;
    exit;
   end;
GetMem(subj, 2 * length(Subject) + 1);//выделяем память
StringToWideChar(Subject, subj, 2 * length(Subject) + 1);//Переводим
result := CertFindCertificateInStore(store, encType, 0, CERT_FIND_SUBJECT_STR,subj, nil);//Ищем по нашему Subject нужный нам сертификат и передаем на result его указатель
FreeMem(subj, 2 * length(Subject) + 1);//Освобождаем память
if result = nil then
   begin
    MessageDlg('Сертификат не найден', mtError, [mbOK], 0);
    CertCloseStore(store, 0);//освобождаем память
    CryptReleaseContext(prov, 0);//освобождаем память
    exit;
   end;
end;


В коментариях все написано, так что пояснять ни чего не буду.

Ну а теперь когда мы получили указатель на сертификать можно аутентифицироваться, в опции к запросу добавляется сертификат и передается запросом.А авторизация системного окна проходит путем, подставления логин/пароля в InternetConnect:
Код

hConnect := InternetConnect(hInternet,PChar('195.161.126.16'),8443,PChar(login){наш логин в системном окне},PChar(password){наш пароль в системном окне},INTERNET_SERVICE_HTTP,0,1);


Ну а теперь привожу листинк функции полностью :
Код

function Authentication_and_SysAuthorization(url,login,password : string) : ansistring;
const
  INTERNET_OPTION_CLIENT_CERT_CONTEXT = 84;//Стандартный флаг для отправки запроса с ручным построением аутентификацие
label 10;
var
  FHost,FScript : string;
  hInternet,hConnect,hRequest : Pointer;
  dwBytesRead,I,L : Cardinal;
  Flags_connection,Flags_Request : Cardinal;
  dwError, dwErrorCode,flags_security : DWORD;
  data : pointer;
  Sertificat : PCCERT_CONTEXT;
begin
  result := '';
  if (login = '') or (password = '') then exit;//Выходи если не задано логин/пароля для авторизации

  fHost := GetHostName(url);
  fScript := GetScriptName(url,fHost);

  //Устанавливаем флаги в данном случае мы не используем стандартный https порт - 443 и по этому Flags_connection - нам не подходит
  SetFlags(url,Flags_connection,Flags_Request);
  //Инициализируем WinInet
  hInternet := InternetOpen(PChar(Application.ExeName),INTERNET_OPEN_TYPE_PRECONFIG,Nil,Nil,0);
  if Assigned(hInternet) then
    begin
      //Открываем сессию
      hConnect := InternetConnect(hInternet,PChar('195.161.126.16'),8443,PChar(login){наш логин в системном окне},PChar(password){наш пароль в системном окне},INTERNET_SERVICE_HTTP,0,1);
      if Assigned(hConnect) then
        begin
          //Формируем запрос
          hRequest := HttpOpenRequest(hConnect,PChar('GET'),PChar(fScript),HTTP_VERSION,nil,Nil,Flags_Request ,1);
          if Assigned(hRequest) then
            begin
10:
              //Отправляем запрос
              I := 1;
              if HttpSendRequest(hRequest,{PChar(Type_Acess)}nil,{length(Type_Acess)}0,{PChar(param)}nil,{length(param)}0)  then
                begin
                  repeat
                  DataAvailable(hRequest, L);//Получаем кол-во принимаемых данных
                  if L = 0 then break;
                  SetLength(result,L + I);
                  if InternetReadFile(hRequest,@result[I],sizeof(L),dwBytesRead) then//Получаем данные с сервера и заносим их в результ
                  else break;

                  inc(I,dwBytesRead);//Обновляем величину переменной
                  until dwBytesRead = 0;
                  result[I] := #0;
                end;
            end;
            //опредиляем код ошибки, нам нужен 12044 - код не прохождения аутентификации
            dwErrorCode := GetLastError;
            //Если код 12044, то добавляем в запрос сертификат из хранилища для прохождения аутентификации
            if  dwErrorCode = ERROR_INTERNET_CLIENT_AUTH_CERT_NEEDED then
              begin
                //Обрабатываем программное подставление сертификата
                //Возможны 4 варианта хранилищ сертификатов
                //MY - для хранения сертификатов отдельного пользователя
                //СА - от Certification Authority - для хранения сертификатов центров сертификации
                //ROOT - для хранения корневых сертификатов
                //А также тан называемое хранилище колекции сертификатов создаваемое исключительно программистом под себя
                //Находим наш сертификат по умолчанию они сохраняются всегда в MY после того как вы откроете вашу страницу любым из браузеров
                Sertificat := FindCertificate('******************************Nikolaevich','my');
                //Добавляем в опции передаваемые с запросом
                InternetSetOptionw(hRequest,INTERNET_OPTION_CLIENT_CERT_CONTEXT,Sertificat,SIZEOF(cert_context));
                //также в опции запроса добавим флаги,
                //как иногда у меня был глюк что они не передавались когда описывались в форме HttpOpenRequest
                flags_security := SECURITY_FLAG_IGNORE_UNKNOWN_CA or
                                  INTERNET_FLAG_IGNORE_CERT_CN_INVALID or
                                  INTERNET_FLAG_IGNORE_CERT_DATE_INVALID or INTERNET_FLAG_NO_AUTH;
                //Добавляем в опции передаваемые с запросом
                InternetSetOptionw(hRequest,INTERNET_OPTION_SECURITY_FLAGS,@flags_security,SIZEOF(DWord));
                //можно передавать пароль и логин здесь кому как интересно, но мне кажется в InternetConnection легче :-)
                //InternetSetOption(hRequest, INTERNET_OPTION_USERNAME, PChar(Login), length(Login));
                //InternetSetOption(hRequest, INTERNET_OPTION_PASSWORD, PChar(Password), length(Password));
                //Освобождаем память от сертификата
                CertFreeCertificateContext(Sertificat);
                //Переходим опять на запрос
                goto 10;
                //Тут закоментен диалог вывода на экран формы выбора сертификата если кому нужно)))
                //dwError := InternetErrorDlg(Form2.Handle, hRequest, dwErrorCode, FLAGS_ERROR_UI_FILTER_FOR_ERRORS or FLAGS_ERROR_UI_FLAGS_CHANGE_OPTIONS or FLAGS_ERROR_UI_FLAGS_GENERATE_DATA,data);
              end;
            InternetCloseHandle(hRequest);
        end;
        InternetCloseHandle(hConnect);
    end;
    InternetCloseHandle(hInternet);
end;



Код пояснять не буду, так как в коментариях и описании выше все становится ясно.

В конце хочу отметить, что если возвращается код в виде абрыкадабры, то это означает что у сервера ответ в виде кодировки UTF8, смените AnsiString->UTF8string или обратно.

Надеюсь данная статья вам поможет, думаю мое полутора недельное исследование данного вопроса вам поможет,а мне репутацию увеличитsmile

Спасибо всем кто меня слушал, с уважением Анатолий "Anatol_rus" Федоров

Это сообщение отредактировал(а) Brausman - 23.10.2009, 00:02

Присоединённый файл ( Кол-во скачиваний: 46 )
Присоединённый файл  Find_Sertificat_and_wcrypt2_pas_file.rar 225,59 Kb
PM MAIL   Вверх
Brausman
Дата 22.10.2009, 19:55 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 26
Регистрация: 1.4.2009

Репутация: 2
Всего: 1



Также прикрепляю проект на Delphi 2009 и надеюсь, что данную статью прикрепят.

Это сообщение отредактировал(а) Brausman - 22.10.2009, 20:00

Присоединённый файл ( Кол-во скачиваний: 65 )
Присоединённый файл  Autorization_from_EGRUL.rar 341,41 Kb
PM MAIL   Вверх
darkmamba
Дата 23.10.2009, 12:47 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 98
Регистрация: 16.10.2008

Репутация: 1
Всего: 1



Статья хорошая, НО хотелось бы побольше информации по авторизации в окне виндоус... у меня стоит Д7 скачал компонент v1.5 а там функции InternetConnect() нету =) подскажите где найти компонент для Д7, д2009 не предлагать  smile 

PM MAIL   Вверх
Brausman
Дата 23.10.2009, 20:35 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 26
Регистрация: 1.4.2009

Репутация: 2
Всего: 1



Цитата(darkmamba @ 23.10.2009,  12:47)
Статья хорошая, НО хотелось бы побольше информации по авторизации в окне виндоус... у меня стоит Д7 скачал компонент v1.5 а там функции InternetConnect() нету =) подскажите где найти компонент для Д7, д2009 не предлагать  smile

InternetConnect - это стандартная Win 32 API функция, просто подключите
Код

uses WinInet;


И все будет.
По поводу системного окна описано в пункте 6 моей статьи, вот цитирую:
Код

А авторизация системного окна проходит путем, подставления логин/пароля в InternetConnect:
hConnect := InternetConnect(hInternet,PChar('195.161.126.16'),8443,PChar(login){наш логин в системном окне},PChar(password){наш пароль в системном окне},INTERNET_SERVICE_HTTP,0,1);


PM MAIL   Вверх
darkmamba
Дата 24.10.2009, 22:38 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 98
Регистрация: 16.10.2008

Репутация: 1
Всего: 1



Все понял но вылетают эти ошибки при InternetOpen и InternetConnect 00CC0008 и 00CC0004

а вот код 

Код

procedure TForm1.Button1Click(Sender: TObject);
var
  pConnect, hInet : Pointer;
begin
hInet := InternetOpen(PChar(Application.ExeName),INTERNET_OPEN_TYPE_PRECONFIG,0,0,0);
pConnect := InternetConnect(hInet, PChar('212.33.232.164'), 80, PChar('123123'), PChar('123123'), INTERNET_SERVICE_HTTP, 0, 1);
end;

PM MAIL   Вверх
Brausman
Дата 25.10.2009, 00:47 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 26
Регистрация: 1.4.2009

Репутация: 2
Всего: 1



Цитата(darkmamba @ 24.10.2009,  22:38)
Все понял но вылетают эти ошибки при InternetOpen и InternetConnect 00CC0008 и 00CC0004

а вот код 

Код

procedure TForm1.Button1Click(Sender: TObject);
var
  pConnect, hInet : Pointer;
begin
hInet := InternetOpen(PChar(Application.ExeName),INTERNET_OPEN_TYPE_PRECONFIG,0,0,0);
pConnect := InternetConnect(hInet, PChar('212.33.232.164'), 80, PChar('123123'), PChar('123123'), INTERNET_SERVICE_HTTP, 0, 1);
end;

А Запрос то к серверу кто будет делать? он делается функциями httpSendRequest
То что вы привели, вы просто назначали имя интернет сессии с которой сервер будет общаться и назвали имя сервера больше ни чего
Код

if Assigned(pConnect) then
//Формируем запрос
          hRequest := HttpOpenRequest(hConnect,PChar(uppercase(method)),PChar(fScript),HTTP_VERSION,nil,Nil,Flags_Request,1);
          if Assigned(hRequest) then
            begin
              //Отправляем запрос
              I := 1;
              if HttpSendRequest(hRequest,nil,0,nil,0) then
                begin
                   repeat
                  DataAvailable(hRequest, L);//Получаем кол-во принимаемых данных
                  if L = 0 then break;
                  SetLength(result,L + I);
                  if InternetReadFile(hRequest,@result[I],sizeof(L),dwBytesRead) then//Получаем данные с сервера и заносим их в результ
                  else break;
                  inc(I,dwBytesRead);//Обновляем величину переменной
                  until dwBytesRead = 0;
                  result[I] := #0;
                end;
            end;
end;


В статье же все написано и ссылки хорошие доны на объяснение функций, а если ошиблки не понятные лезут пользуйтесь функцией GetLastError;
method - то GET или Post, в зависимости от того что вы делаете
fScript - куда вы переходите по серверу
Flags_Request - флаги которые вы задали для данного запроса к серверу

Это сообщение отредактировал(а) Brausman - 25.10.2009, 01:00
PM MAIL   Вверх
MetalFan
  Дата 25.10.2009, 10:01 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Аццкий Сотона
****


Профиль
Группа: Комодератор
Сообщений: 3815
Регистрация: 2.10.2006
Где: Moscow

Репутация: 14
Всего: 128



спасибо. кое с чем не сталкивался (с сертификатами). хотя тут все рассмотрено поверхностно и в итоге я все равно толком не понял что почему и как (касательно сертификатов).
Цитата(Brausman @  22.10.2009,  19:24 Найти цитируемый пост)
Автор предупреждает, что не будет вступать в споры по поводу оптимизации кода, данная статья не про это

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

а в целом, если причесать, то весьма познавательно для тех, кто с этой темой сталкивается впервые.

Это сообщение отредактировал(а) MetalFan - 25.10.2009, 12:42


--------------------
There are always someone smarter than you...
PM MAIL   Вверх
darkmamba
Дата 25.10.2009, 16:23 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 98
Регистрация: 16.10.2008

Репутация: 1
Всего: 1



Вобщем я запутался, помогите разгрести кучу.

Код

procedure TForm1.Button1Click(Sender: TObject);
var
  hRequest, hConnect, hInet : Pointer;
  BufferLength, Reserved, ReadedSize, Size : cardinal;
  Buff : ANSIString;
begin
hInet := InternetOpen(PChar('Adios!'),INTERNET_OPEN_TYPE_PRECONFIG,0,0,0);
hConnect := InternetConnect(hInet, PChar('212.33.232.164'), 80, PChar('123123'),   //212.33.232.164
            PChar('123123'), INTERNET_SERVICE_HTTP, 0, 1);
hRequest := HttpOpenRequest(hConnect, 0,pchar('www.l2r.ru/admin'),
            HTTP_VERSION, 0, 0, 1, 1); - Здесь вылазит 122 ошибка
HttpSendRequest(hRequest, 0, 0, 0, 0); - Здесь 12150
 MessageBox(0, pchar(IntToStr(GetLastError)), pchar('GetLastError'),0);
if InternetQueryDataAvailable(hRequest, size, 0, 0) then messagebox(0,pchar(IntToStr(Size)),pchar('InternetQueryDataAvailable'),0);
SetLength(Buff, 1024);
InternetReadFile(hRequest, @Buff[1], size, ReadedSize);
showmessage(buff); // это просто для наглядности..


Вылазят какието ошибки, природу понять немогу. Вроде все делаю так как написано, а не работает хз почему.

Update
Непонятным образом ошибка 12150 испарилась!!! 122 попрежнему вылетает но видимо не фатально, но разобратся бы хотелось всеравно!

Шас вылазит типа HTTPProtocolException 403 Forbiden или по-русски нет доступа, через браузер вылазит 401 Необходима авторизация... тупик... может какой флаг надо поставить ???

Это сообщение отредактировал(а) darkmamba - 25.10.2009, 19:43
PM MAIL   Вверх
Brausman
Дата 25.10.2009, 19:55 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 26
Регистрация: 1.4.2009

Репутация: 2
Всего: 1



Цитата(MetalFan @ 25.10.2009,  10:01)
спасибо. кое с чем не сталкивался (с сертификатами). хотя тут все рассмотрено поверхностно и в итоге я все равно толком не понял что почему и как (касательно сертификатов).
Цитата(Brausman @  22.10.2009,  19:24 Найти цитируемый пост)
Автор предупреждает, что не будет вступать в споры по поводу оптимизации кода, данная статья не про это

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

а в целом, если причесать, то весьма познавательно для тех, кто с этой темой сталкивается впервые.

Спасибо за критику учту, но давайте по порядку:
1. На счет сертификатов, в статье написано, что прилагается программка моя через ,которую можно узнать Subject, своего сертификата, потом это полное subject, подставляешь в мою функцию FindCertificate, и далее указатель передаешь в InternetSetOption, вот в принципе и все и ни чего сложного smile
2. На счет грамматике русской - ет да признаю она у меня плоха, но какое оно имеет отношение к статье?
3. Я писал что код не претендует на оптимальность, нро все же объясните почему вам так не нравится переход goto,там ни какого дубляжа нет, так как в любом случае надо вызывать функцию HttpSendRequest?
4. В чем проявляется плохая читаемость кода?? Если не сложно приведите ссылку или напишите фрагмент  хорошо читаемого кода.
5. Ну и скажите что причесывать, чтоб можно было привести статью к завершенному виду, так как опыта в написании статей у меня не было.

Это конечно начался флуд но все равно, интересно узнать на мои вопросы ответы.
PM MAIL   Вверх
darkmamba
Дата 25.10.2009, 20:07 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 98
Регистрация: 16.10.2008

Репутация: 1
Всего: 1



Ура, запрос отправился нормальный!!!! Относительно! Неотправляются пароль и логин в базе64....

Странно, но почемуто отправляется 2 запроса сразу, в 1ом нету логина и пароля во втором есть, это че прикол такой ?

Это сообщение отредактировал(а) darkmamba - 25.10.2009, 20:13
PM MAIL   Вверх
Brausman
Дата 25.10.2009, 20:14 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 26
Регистрация: 1.4.2009

Репутация: 2
Всего: 1



Цитата(darkmamba @ 25.10.2009,  16:23)
Вобщем я запутался, помогите разгрести кучу.

Код

procedure TForm1.Button1Click(Sender: TObject);
var
  hRequest, hConnect, hInet : Pointer;
  BufferLength, Reserved, ReadedSize, Size : cardinal;
  Buff : ANSIString;
begin
hInet := InternetOpen(PChar('Adios!'),INTERNET_OPEN_TYPE_PRECONFIG,0,0,0);
hConnect := InternetConnect(hInet, PChar('212.33.232.164'), 80, PChar('123123'),   //212.33.232.164
            PChar('123123'), INTERNET_SERVICE_HTTP, 0, 1);
hRequest := HttpOpenRequest(hConnect, 0,pchar('www.l2r.ru/admin'),
            HTTP_VERSION, 0, 0, 1, 1); - Здесь вылазит 122 ошибка
HttpSendRequest(hRequest, 0, 0, 0, 0); - Здесь 12150
 MessageBox(0, pchar(IntToStr(GetLastError)), pchar('GetLastError'),0);
if InternetQueryDataAvailable(hRequest, size, 0, 0) then messagebox(0,pchar(IntToStr(Size)),pchar('InternetQueryDataAvailable'),0);
SetLength(Buff, 1024);
InternetReadFile(hRequest, @Buff[1], size, ReadedSize);
showmessage(buff); // это просто для наглядности..


Вылазят какието ошибки, природу понять немогу. Вроде все делаю так как написано, а не работает хз почему.

Update
Непонятным образом ошибка 12150 испарилась!!! 122 попрежнему вылетает но видимо не фатально, но разобратся бы хотелось всеравно!

Шас вылазит типа HTTPProtocolException 403 Forbiden или по-русски нет доступа, через браузер вылазит 401 Необходима авторизация... тупик... может какой флаг надо поставить ???

1.Обратите внимание что передается в HttpSendRequest вместо:
Код

HttpSendRequest(hRequest, 0, 0, 0, 0); - Здесь 12150

надо
Код

HttpSendRequest(hRequest, nil, 0, nil, 0); 

Это на первый взгляд,что я увидел
И еще вот ссылка на все ошибки winineta - http://support.microsoft.com/kb/193625
там ясно сказано,что передаваемый заголовок не может быть обнаружен

2.hRequest := HttpOpenRequest(hConnect, 0,pchar('www.l2r.ru/admin'),HTTP_VERSION, 0, 0, 1, 1); - Здесь вылазит 122 

если я правильно понимаю, то www.l2r.ru - это имя сервера, а в HttpOpenRequest передается не имя сервера, а скрипт который должен выполнится на нем, т.е. admin, потом после HTTP_VERSION должны идти не 0 , а nil , после nil(первая 1 - там должны стоять флаги запроса к серверу), в статье, это все подробным образом описано,
про флаги
Код

procedure SetFlags(url : string; out Flags_connection,Flags_Request : Cardinal);
begin
  //Оприделяем на https или http
  if pos('https',url) > 0 then
    begin
      Flags_connection := INTERNET_DEFAULT_HTTPS_PORT;
      Flags_Request := INTERNET_FLAG_RELOAD or INTERNET_FLAG_IGNORE_CERT_CN_INVALID or INTERNET_FLAG_NO_CACHE_WRITE or INTERNET_FLAG_SECURE or INTERNET_FLAG_PRAGMA_NOCACHE or INTERNET_FLAG_KEEP_CONNECTION;
    end
  else
    begin
      Flags_connection := INTERNET_DEFAULT_HTTP_PORT;
      Flags_Request := INTERNET_FLAG_RELOAD or INTERNET_FLAG_IGNORE_CERT_CN_INVALID or INTERNET_FLAG_NO_CACHE_WRITE or INTERNET_FLAG_PRAGMA_NOCACHE or INTERNET_FLAG_KEEP_CONNECTION;
    end;
end;

Где Flags_Request и подставляется в HttpOpenRequest, и в конечном виде она будет такой:
Код

HttpOpenRequest(hConnect, 0,pchar('admin'),HTTP_VERSION, nil,nil, Flags_Request, 1); 


и про скрипты:
Код


б) Идем дальше)), в функцию 
HttpOpenRequest
 передается параметр
lpszObjectName
 - он же скрипт, также берется из полного url, из
http://www.delphisources.ru/pages/faq/base/inet_win32_api_functions.html  скрипт будет 
pages/faq/base/inet_win32_api_functions.html ,для его вытаскивания служит следующая функция :

function GetScriptName( url,hostname : string) : string;
begin
  result := '';
  delete(url,1,pos(hostname,url) + length(hostname));
  result := url;
end;




3. 
Код

InternetOpen(PChar('Adios!'),INTERNET_OPEN_TYPE_PRECONFIG,0,0,0); 
- это у вас
а надо так
Код

InternetOpen(PChar('Adios!'),INTERNET_OPEN_TYPE_PRECONFIG,nil,nil,0);

 прежде чем задавать вопрос, посмотрите статью и только после того как не найдете там ответа на свой вопрос, пишите его здесь.

Это сообщение отредактировал(а) Brausman - 25.10.2009, 20:18
PM MAIL   Вверх
darkmamba
Дата 25.10.2009, 20:23 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 98
Регистрация: 16.10.2008

Репутация: 1
Всего: 1



На самом деле это абсолютно рабочий код, можете поверить или проверить(просто я неуспел обновить еще тот пост)! Одно НО отправляется 2 запроса с разницей в доли секунды, это не есть хорошо.... пока что незнаю почему можете присоединится!

По поводу NIL , делфи конвертирует 0 в NILы где надо.....

Код

var
  hRequest, hConnect, hInet : Pointer;
  BufferLength, Reserved, ReadedSize, Size : cardinal;
  Buff : ANSIString;
  headers : string;
begin

hInet := InternetOpen(PChar('Голактико Вопасносте!'),INTERNET_OPEN_TYPE_PRECONFIG,0,0,0);

hConnect := InternetConnect(hInet, PChar('www.l2r.ru'), 80, PChar('123123'),   //212.33.232.164
            PChar('123123'), INTERNET_SERVICE_HTTP, 0, 1);

hRequest := HttpOpenRequest(hConnect, 0,pchar('/admin'),
            HTTP_VERSION, 0, 0,
            INTERNET_FLAG_NO_COOKIES+
            INTERNET_FLAG_KEEP_CONNECTION, 1);

HttpSendRequest(hRequest, 0, 0, 0, 0);
InternetQueryDataAvailable(hRequest, size, 0, 0);
SetLength(Buff, 1024);
InternetReadFile(hRequest, @Buff[1], size, ReadedSize);
showmessage(buff);


Это сообщение отредактировал(а) darkmamba - 25.10.2009, 20:28
PM MAIL   Вверх
MetalFan
Дата 25.10.2009, 21:16 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Аццкий Сотона
****


Профиль
Группа: Комодератор
Сообщений: 3815
Регистрация: 2.10.2006
Где: Moscow

Репутация: 14
Всего: 128



darkmamba, может стоить создать отдельную тему по своим повросам? твои эксперименты, имхо, хоть со статьей и связаны, но не являются ни ее обсуждением, ни продолжением.


--------------------
There are always someone smarter than you...
PM MAIL   Вверх
MetalFan
Дата 25.10.2009, 21:35 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Аццкий Сотона
****


Профиль
Группа: Комодератор
Сообщений: 3815
Регистрация: 2.10.2006
Где: Moscow

Репутация: 14
Всего: 128



Цитата(Brausman @  25.10.2009,  19:55 Найти цитируемый пост)
1. На счет сертификатов, в статье написано, что прилагается программка моя через ,которую можно узнать Subject, своего сертификата, потом это полное subject, подставляешь в мою функцию FindCertificate, и далее указатель передаешь в InternetSetOption, вот в принципе и все и ни чего сложного smile 
что значит "свой" сертификат? откуда он взялся? зачем он может понадобится серверу? код то я посмотрел, что он делает в целом ясно. но вот предпосылок к его использованию я не понял.

Цитата(Brausman @  25.10.2009,  19:55 Найти цитируемый пост)
2. На счет грамматике русской - ет да признаю она у меня плоха, но какое оно имеет отношение к статье?
такое, что материал на порядок хуже воспринимается с грамматическими и синтаксическими ошибками, чем без них.

Цитата(Brausman @  25.10.2009,  19:55 Найти цитируемый пост)
3. Я писал что код не претендует на оптимальность, нро все же объясните почему вам так не нравится переход goto,там ни какого дубляжа нет, так как в любом случае надо вызывать функцию HttpSendRequest? 

goto усложняет восприятие кода, запутывает его. лично я против использования этого атавизма. но не будем затевать здесь холивар)
дубляж. в функции FindCertificate два практически одинаковых блока с exit'ами. мелочь, но на глаза попалась.
так же нет ни одного блока try..finally...

Цитата(Brausman @  25.10.2009,  19:55 Найти цитируемый пост)
4. В чем проявляется плохая читаемость кода?? Если не сложно приведите ссылку или напишите фрагмент  хорошо читаемого кода. 

бросилось в глаза, что тело цикла repeat..until написано без отступа...
ну и таких мелких ляпов можно набрать еще несколько штук.
я не претендую на идеального оформителя кода, но можешь посмотреть пример моего компонента-обертки над WinInet.

Цитата(Brausman @  25.10.2009,  19:55 Найти цитируемый пост)
5. Ну и скажите что причесывать, чтоб можно было привести статью к завершенному виду, так как опыта в написании статей у меня не было. 

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

з.ы. ну и можно я думаю на "ты". мы же с вами культурные люди)


--------------------
There are always someone smarter than you...
PM MAIL   Вверх
Brausman
Дата 25.10.2009, 23:37 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 26
Регистрация: 1.4.2009

Репутация: 2
Всего: 1



В целом нарекания понятны, твою обертку над wininet видел,сделано не дурно, нет try ...finally.. так как делал просто примеры, без учета обработки всякого рода глюков.
На счет "своего" сертификата, это когда(я кстати с этим сам встретился 1 раз) тебе, например налоговая дает на руки индивидуальный сертификат для доступа в их базу данных по налогоплательщикам(ет из практики),сервер каждую сессию обращается к тебе сначала за подтверждением сертификата, а уж потом за логином/паролем, этот сертификат как раз через IE(или другой браузер) добавляется в хранилище "MY" сертификатов откуда я его и использую, по данной теме инфы в интернете вообще не нашел, так что посчитал правильным добавить его в статью.

Ну а статью на недели когда время будет поправлю.
PM MAIL   Вверх
Brausman
Дата 25.10.2009, 23:58 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 26
Регистрация: 1.4.2009

Репутация: 2
Всего: 1



darkmamba, как можно быть таким не внимательным или вы статью не читали?????
Код

hRequest := HttpOpenRequest(hConnect, 0,pchar('/admin'),
HTTP_VERSION, 0, 0,
INTERNET_FLAG_NO_COOKIES+
INTERNET_FLAG_KEEP_CONNECTION, 1);

Скрип передается без "/" ,если у вас www.l2r.ru/admin, то скрипт будет adminбез "/"!!!
Код

hRequest := HttpOpenRequest(hConnect, 0,pchar('admin'),
            HTTP_VERSION, 0, 0,
            INTERNET_FLAG_NO_COOKIES+
            INTERNET_FLAG_KEEP_CONNECTION, 1);

 И проверьте метод передачи, я вижу у вас метод "GET", там точно этот метод??

Это сообщение отредактировал(а) Brausman - 25.10.2009, 23:59
PM MAIL   Вверх
MetalFan
Дата 26.10.2009, 11:45 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Аццкий Сотона
****


Профиль
Группа: Комодератор
Сообщений: 3815
Регистрация: 2.10.2006
Где: Moscow

Репутация: 14
Всего: 128



Brausman, спасибо, про "свой" сертификат прояснилось) ни разу сам с таким не сталкивался, теперь буду знать. хотя эту тему можно осветить вообще отдельно.

в любом случае ты молодец, что решился написать такую полезную статью!
после небольшого "причесывания" цены ей не будет)
с почином, так держать!



--------------------
There are always someone smarter than you...
PM MAIL   Вверх
Brausman
Дата 26.10.2009, 12:56 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 26
Регистрация: 1.4.2009

Репутация: 2
Всего: 1



Цитата(MetalFan @ 26.10.2009,  11:45)
Brausman, спасибо, про "свой" сертификат прояснилось) ни разу сам с таким не сталкивался, теперь буду знать. хотя эту тему можно осветить вообще отдельно.

в любом случае ты молодец, что решился написать такую полезную статью!
после небольшого "причесывания" цены ей не будет)
с почином, так держать!

Спасибо, в принципе можно написать статью, как делать/регистрировать в хранилищах/использовать свои сертификаты тоже, хотя думаю такая статья отклика в массах не получит smile 
PM MAIL   Вверх
darkmamba
Дата 26.10.2009, 13:36 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 98
Регистрация: 16.10.2008

Репутация: 1
Всего: 1



Цитата(Brausman @ 25.10.2009,  23:58)
darkmamba, как можно быть таким не внимательным или вы статью не читали?????
Код

hRequest := HttpOpenRequest(hConnect, 0,pchar('/admin'),
HTTP_VERSION, 0, 0,
INTERNET_FLAG_NO_COOKIES+
INTERNET_FLAG_KEEP_CONNECTION, 1);

Скрип передается без "/" ,если у вас www.l2r.ru/admin, то скрипт будет adminбез "/"!!!
Код

hRequest := HttpOpenRequest(hConnect, 0,pchar('admin'),
            HTTP_VERSION, 0, 0,
            INTERNET_FLAG_NO_COOKIES+
            INTERNET_FLAG_KEEP_CONNECTION, 1);

 И проверьте метод передачи, я вижу у вас метод "GET", там точно этот метод??

метод GET, по дефолту выставляется если поставить 0 (mdsn).

В общем все работает, только отправляется по 2 запроса (одинаковых), только первый без аутенфикации (без пароля и логина), они приходят во втором с разницей в доли секунды.. т.е сразу же на ответ от сервера как я понимаю... почему не сразу - хз.

Код

15:40:00:421  0,016 s      GET     401     651       text/html  http://www.l2r.ru/admin               
GET /admin HTTP/1.1
User-Agent: Голактико Вопасносте!
Host: www.l2r.ru
Connection: Keep-Alive

15:40:00:437  0,015 s      GET     401     651       text/html  http://www.l2r.ru/admin               
GET /admin HTTP/1.1
User-Agent: Голактико Вопасносте!
Host: www.l2r.ru
Connection: Keep-Alive
Authorization: Basic TWluaWJ1a2E6MTIzMTIzMTIzMTIz


Можно сказать, что проблему решил, используя собственые хедеры, в которых сам кодирую пароль и логин в базе64, только вот есть ли разница между MTIzNDU2OjY1NDMyMQ== и MTIzNDU2OjY1NDMyMQ (это 123456:654321)? При раскодировке нету  smile 

Это сообщение отредактировал(а) darkmamba - 26.10.2009, 19:14
PM MAIL   Вверх
Brausman
Дата 26.10.2009, 20:22 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 26
Регистрация: 1.4.2009

Репутация: 2
Всего: 1



А что тут удивительного, если идет аутетификация то сервер ждет когда вы ему подсунете нужный сертификат(это первый GET), потом так как у нас включен редирект, он сразу (наш WinInet) посылает серверу запрос ответ авторизации(ваш закодированный логин/пароль) - это 2 GET.

А на счет пароля отсылаемые данные серверу должны быть идентичны.
И зачем кодировать самому, если через InternetConnection, логин/пароль сами кодируются WinInet'ом.
PM MAIL   Вверх
darkmamba
Дата 27.10.2009, 14:06 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 98
Регистрация: 16.10.2008

Репутация: 1
Всего: 1



Чтобы не было лишнего запроса.
PM MAIL   Вверх
Страницы: (2) [Все] 1 2 
Ответ в темуСоздание новой темы Создание опроса
Правила форума "Delphi: Сети"
Snowy
Poseidon
MetalFan

Запрещено:

1. Публиковать ссылки на вскрытые компоненты

2. Обсуждать взлом компонентов и делится вскрытыми компонентами

  • Литературу по Дельфи обсуждаем здесь
  • Действия модераторов можно обсудить здесь
  • С просьбами о написании курсовой, реферата и т.п. обращаться сюда
  • Вопросы по реализации алгоритмов рассматриваются здесь
  • 90% ответов на свои вопросы можно найти в DRKB (Delphi Russian Knowledge Base) - крупнейшем в рунете сборнике материалов по Дельфи

Если Вам помогли и атмосфера форума Вам понравилась, то заходите к нам чаще! С уважением, Snowy, Poseidon, MetalFan.

 
1 Пользователей читают эту тему (1 Гостей и 0 Скрытых Пользователей)
0 Пользователей:
« Предыдущая тема | Delphi: Сети | Следующая тема »


 




[ Время генерации скрипта: 0.1488 ]   [ Использовано запросов: 23 ]   [ GZIP включён ]


Реклама на сайте     Информационное спонсорство

 
По вопросам размещения рекламы пишите на vladimir(sobaka)vingrad.ru
Отказ от ответственности     Powered by Invision Power Board(R) 1.3 © 2003  IPS, Inc.