Как ответить на дайджест аутентификации доступа с помощью Indy - PullRequest
1 голос
/ 15 января 2020

Я пытаюсь отправить ответ обратно на серверы, запрашивающие дайджест-аутентификацию доступа

  ....
  FResponseHeader.Text := FResponseText;// received header.
  FResponseHeader.ProcessHeaders;
   ....
  WriteLn(FResponseHeader.WWWAuthenticate); //WWW-Authenticate: Digest realm="xxxx.com", nonce="fq1uvocyzvr17e6a5syproazd5phwdvhvlc5", stale=false, algorithm=MD5, qop="auth"
  LIdAuthentication := TIdDigestAuthentication.Create;
  try
    LIdAuthentication.Username := FUser;
    LIdAuthentication.Password := FPass;
    LIdAuthentication.Uri      := FURI;
    LIdAuthentication.Method   := GetMsgTypeString(FResponseHeader.RequestMethods);
    LIdAuthentication.Params.Values['Authorization'] := FResponseHeader.WWWAuthenticate;
    LIdAuthentication.AuthParams.AddValue('Digest', FResponseHeader.WWWAuthenticate);
    for I := 0 to LIdAuthentication.Steps do
      LIdAuthentication.Next;
    Result := LIdAuthentication.Authentication;
  finally
    LIdAuthentication.Free;
  end;

Я получил 401 с сервера.

Как правильно создать Заголовок авторизации ?

1 Ответ

3 голосов
/ 15 января 2020

TIdDigestAuthentication (и другие классы TIdAuthentication) предназначены для использования с TIdHTTP, а не автономно.

Если вы используете TIdHTTP для связи с сервером, вы делаете вообще не нужно управлять дайджест-аутентификацией вручную. Если сервер запрашивает Digest в своем заголовке WWW-Authenticate и если IdAuthenticationDigest (или IdAllAuthentications) содержится в предложении uses, то TIdHTTP автоматически отправит вам дайджест-ответ. Единственное, о чем вам стоит позаботиться, это:

  • установить свойства TIdHTTP.Request.Username и TIdHTTP.Request.Password для начальной попытки аутентификации.

  • установите обработчик событий TIdHTTP.OnAuthorization, чтобы обработать возможность отклонения сервером текущего Username / Password, чтобы вы могли предоставить новые значения для повторной попытки, опционально после запроса пользователя.

  • дополнительно установите обработчик события TIdHTTP.OnSelectProxyAuthorization, чтобы выбрать, какую схему аутентификации использовать, если сервер запрашивает несколько схем, и / или если вы хотите контролировать, какая схема имеет приоритет над другими.

Например:

uses
  ..., IdHTTP, IdAuthenticationDigest;

...

IdHTTP1.OnAuthorization := AuthRequested;
IdHTTP1.Request.Username := ...; // initial username
IdHTTP1.Request.Password := ...; // initial password
IdHTTP1.Get(...);

...

procedure TMyClass.AuthRequested(Sender: TObject; Authentication: TIdAuthentication; var Handled: Boolean);
begin
  if (new credentials are available) then
  begin
    Authentication.Username := ...; // new username
    Authentication.Password := ...; // new password
    Handled := True;
  end else
    Handled := False;
end;

При этом, если вы хотите использовать TIdDigestAuthentication в автономном режиме, вы должны использовать его так же, как TIdHTTP, например:

LIdAuthentication := TIdDigestAuthentication.Create;
try
  LIdAuthentication.SetRequest(FGetMsgTypeString(FResponseHeader.RequestMethods), FURI);
  LIdAuthentication.Username := FUser;
  LIdAuthentication.Password := FPass;
  LIdAuthentication.Params.Values['Authorization'] := LIdAuthentication.Authentication;
  LIdAuthentication.AuthParams := FResponseHeader.WWWAuthenticate; // assuming WWWAuthenticate is a TIdHeaderList...

  repeat
    case LIdAuthentication.Next of
      wnAskTheProgram:
      begin
        // set LIdAuthentication.Username and LIdAuthentication.Password to new credentials to retry...
      end;

      wnDoRequest:
      begin
        // send new request with LIdAuthentication.Authentication in the 'Authorization' header...
        Result := LIdAuthentication.Authentication;
        Exit;
      end;

      wnFail:
      begin
        // error handling ...
        Result := '';
        Exit;
      end;
    end;
  until False;
finally
  LIdAuthentication.Free;
end;
...