Www-authenticate

Тема в разделе "Delphi - Сети", создана пользователем Lem0nti, 24 июл 2012.

  1. Lem0nti

    Lem0nti Гость

    Дельфя - 2010
    Инди - 10.5.5
    Запрашиваю необходимую мне страницу, на которой необходима авторизация, в обработчике события OnAuthorization присваиваю логин и пароль, ответ - 401. Авторизация не базовая, а Digest (WWW-Authenticate).
    Подскажите, пожалуйста, что необходимо сделать, чтобы авторизация прошла?
     
  2. sinkopa

    sinkopa Well-Known Member

    Регистрация:
    17 июн 2009
    Сообщения:
    344
    Симпатии:
    9
    Для использования в проекте метода авторизации Digest access authentication (класс TIdDigestAuthentication) необходимо подключить юнит IdAuthenticationDigest.pas
    Код (Delphi):
    uses
    {...} IdAuthenticationDigest;
    После этого TIdHTTP (если сервер будет запрашивать этот метод авторизации) автоматически его "подхватит" и будет использовать.
    Т.е. в коде ничего больше добавлять не требуется...

    PS.
    Помнится мне, пару лет назад в модуле IdAuthenticationDigest.pas была бага, которую вручную приходилось подправлять... Надеюсь ее "индийцы" исправили но проверить-убедиться не помешает.
     
  3. Lem0nti

    Lem0nti Гость

    Подключив этот модуль, попробовал такие варианты в событии OnAuthorization:
    - присваиваю логин и пароль
    - присваиваю логин, пароль и урл
    - присваиваю логин, пароль, урл и выполняю метод next
    - создаю новый экземпляр класса TIdDigestAuthentication, проделываю с ним все предыдущие варианты, присваивая его объекту Authentication.

    Все варианты оказываются нерабочими. Не могли бы вы поподробнее описать тот возможный баг? Есть предположение что просто не шлётся целиком строка с хэшами.
     
  4. Lem0nti

    Lem0nti Гость

    Странная ситуация. В общем, я окончательно пришёл к выводу, что проблема в каком-то из неучтённых свойств при использовании компонентов инди. При самостоятельной реализации алгоритмов RFC2617 всё отработало. Привожу код:
    Код (Delphi):
    procedure TForm1.Button1Click(Sender: TObject);
    var
    sl: TStringList;
    S,LstrCNonce,LstrResponse: string;
    st: TFileStream;
    i: Integer;
    function HexToInt(Text: string): Integer;
    const
    Convert: array['0'..'f'] of SmallInt =
    (0, 1, 2, 3, 4, 5, 6, 7, 8, 9,-1,-1,-1,-1,-1,-1,
    -1,10,11,12,13,14,15,-1,-1,-1,-1,-1,-1,-1,-1,-1,
    -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,
    -1,10,11,12,13,14,15);
    var
    I: Integer;
    function Stepen(Number, count: integer): integer;
    var
    I: Integer;
    begin
    if Count=0 then
    result:=1
    else
    begin
    result:=Number;
    for I := 1 to Count - 1 do
    result:=result*Number;
    end;
    end;
    begin
    result:=0;
    for I := length(Text) downto 1 do
    result:=result+Convert[Text[I]]*Stepen(16,length(Text)-i);
    end;
    function RemoveQuote(const aStr: string):string;
    begin
    if (Length(aStr) >= 2) and (aStr[1] = '"') and (aStr[Length(aStr)] = '"') then
    Result:=Copy(aStr,2,Length(aStr)-2)
    else
    Result := aStr;
    end;

    //эта функция просчитывает хэш md5 для передаваемой строки
    function ResultString(const S: String): String;
    begin
    Result := '';
    with TIdHashMessageDigest5.Create do
    try
    Result:=AnsiLowerCase(AsHex(HashValue(s)));
    finally
    Free;
    end;
    end;
    begin
    IdTCPClient.Host:='localhost';
    IdTCPClient.Port:=8550;
    IdTCPClient.Connect;
    try
    IdTCPClient.WriteLn('GET /page.htm HTTP/1.1');
    IdTCPClient.WriteLn('Host: localhost:8550');
    IdTCPClient.WriteLn('');
    sl:=TStringList.Create;
    try
    //тут заранее знаю сколько строк в заголовке
    IdTCPClient.ReadStrings(TStrings(sl),10);
    Memo1.Lines.Assign(sl); //это для красоты, чтобы видеть результат
    if pos('401',sl.Strings[0])>1 then
    begin
    //тут я заранее знаю в какой строке придёт заголовок с указанием на данные, необходимые для ответа
    s:=trim(copy(sl.Strings[5],25,1024));
    sl.Text:=StringReplace(s,', ',#13#10,[rfReplaceAll]); //превращаю в StringList для удобства работы со значениями
    sl.Insert(0,'username="admin"'); //параметр имени пользователя
    sl.Add('uri="/page.htm"'); //параметр запрашиваемой страницы
    LstrCNonce:=ResultString(DateTimeToStr(Now));
    sl.Add('cnonce="'+LstrCNonce+'"'); //добавляю уникальный код, по которому будет вести проверку сервер
    sl.Add('nc=00000001'); //счётчик попыток
    //тут собирается воедино всё что требуется по RFC2617
    //admin в первом случае - логин, во втором - пароль
    LstrResponse:=ResultString(ResultString('admin:'+RemoveQuote(sl.Values['realm'])+':admin')+':'+
    RemoveQuote(sl.Values['nonce'])+':00000001:'+LstrCNonce+
    ':auth:'+ResultString('GET:/page.htm'));
    sl.Add('response="'+LstrResponse+'"');
    s:='Authorization: Digest '+stringreplace(sl.Text,#13#10,',',[rfReplaceAll]);
    Delete(s,length(s),1);
    sl.Clear;
    //отправляем обратно авторизацию
    IdTCPClient.WriteLn('GET /page.htm HTTP/1.1');
    IdTCPClient.WriteLn('Host: localhost:8550');
    IdTCPClient.WriteLn(s);
    IdTCPClient.WriteLn('');
    IdTCPClient.ReadStrings(TStrings(sl),10);
    Memo1.Lines.Assign(sl);
    //тут по идее надо вставить проверку на ответ 200
    //плюс я заранее знаю что для этого примера у меня приходит картинка и chunked передача
    st:=TFileStream.Create('C:\qwe.jpg',fmCreate);
    try
    s:=IdTCPClient.ReadLn;
    while s<>'0' do
    begin
    i:=HexToInt(s);
    IdTCPClient.ReadStream(st,i);
    s:=IdTCPClient.ReadLn;
    s:=IdTCPClient.ReadLn;
    end;
    finally
    FreeAndNil(st);
    end;
    end;
    finally
    FreeAndNil(sl);
    end;
    finally
    IdTCPClient.Disconnect;
    end;
    end;
    Пример сделан на Delphi 7 и сам по себе является повторением алгоритма, реализованного в библиотеке Indy в файле IdAuthenticationDigest. Почему там не работает как надо, непонятно.
     
  5. sinkopa

    sinkopa Well-Known Member

    Регистрация:
    17 июн 2009
    Сообщения:
    344
    Симпатии:
    9
    Охх... давно это было...
    Баг был связан с TStringList через который реквест строчка парсилась или (респонс формировался, точно сейчас не вспомню)... суть в том что в строке урезалась одна двойная кавычка ("), потому что TStringList принимал ее за qutechar...
    Вы лучше сходите на оффсайт и обновитесь в девелоперской ветке:
    http://www.indyproject.org/Sockets/wizard/...dWizard.EN.aspx
    http://www.indyproject.org/Sockets/Docs/In...llation.EN.aspx
    Там же, кстати, документация и рабочие примеры:
    http://www.indyproject.org/Sockets/index.EN.aspx
     
Загрузка...
Похожие Темы - Www authenticate
  1. aleksvalery
    Ответов:
    4
    Просмотров:
    3.257
  2. SkyRanger
    Ответов:
    3
    Просмотров:
    2.750
  3. samurai
    Ответов:
    1
    Просмотров:
    1.569

Поделиться этой страницей