|
Registriert seit: 18. Mär 2004 Ort: Luxembourg 3.492 Beiträge Delphi 7 Enterprise |
#7
Das hat mich jetzt nicht losgelassen. Ich habe etwas bei Indy abgekupfert.
Delphi-Quellcode:
Für den Test mit httbin:
unit REST.Authenticator.Digest;
interface uses System.Classes, Data.Bind.ObjectScope, REST.Client; type TSubDigestAuthenticationBindSource = class; TDigestAuthenticator = class(TCustomAuthenticator) protected FBindSource: TSubDigestAuthenticationBindSource; function CreateBindSource: TBaseObjectBindSource; override; private FPassword: string; FUsername: string; FNonceCount: integer; FQopOptions : TStringList; FRealm : string; FNonce : string; FOpaque : string; FQop : string; FMethod : string; FAlgorithm : string; FUri : string; procedure ReadHeader(ARequest : TCustomRESTRequest); protected procedure SetPassword(const AValue: string); procedure SetUsername(const AValue: string); procedure DoAuthenticate(ARequest: TCustomRESTRequest); override; public constructor Create(const AUsername, APassword: string); reintroduce; overload; constructor Create(AOwner: TComponent); overload; override; destructor Destroy; override; published property Username: string read FUsername write SetUsername; property Password: string read FPassword write SetPassword; end; TSubDigestAuthenticationBindSource = class(TRESTAuthenticatorBindSource<TDigestAuthenticator>) protected function CreateAdapterT: TRESTAuthenticatorAdapter<TDigestAuthenticator>; override; end; TDigestAuthenticatorAdapter = class(TRESTAuthenticatorAdapter<TDigestAuthenticator>) protected procedure AddFields; override; end; implementation uses System.Sysutils, System.Hash, Data.Bind.Components, REST.Consts, REST.Types; { TDigestAuthenticator } constructor TDigestAuthenticator.Create(const AUsername, APassword: string); begin Create(NIL); FUsername := AUsername; FPassword := APassword; end; constructor TDigestAuthenticator.Create(AOwner: TComponent); begin inherited; FNonceCount := 1; FQopOptions := TStringList.Create; end; function TDigestAuthenticator.CreateBindSource: TBaseObjectBindSource; begin FBindSource := TSubDigestAuthenticationBindSource.Create(Self); FBindSource.Name := 'BindSource'; { Do not localize } FBindSource.SetSubComponent(True); FBindSource.Authenticator := Self; result := FBindSource; end; destructor TDigestAuthenticator.Destroy; begin FQopOptions.Free; inherited; end; procedure TDigestAuthenticator.DoAuthenticate(ARequest: TCustomRESTRequest); function Hash(const AString : string) : string; begin Result := THashMD5.GetHashString(AString); end; var LCNonce : string; LA1 : string; LA2 : string; LResponse : string; LResult : string; begin if ARequest.Response.StatusCode <> 401 then Exit; ReadHeader(ARequest); LCNonce := Hash(DateTimeToStr(Now)); LA1 := Username + ':' + FRealm + ':' + Password; {do not localize} LA2 := FMethod + ':' + FUri; {do not localize} LResponse := IntToHex(FNonceCount, 8) + ':' + LCNonce + ':' + FQop + ':'; {do not localize} LResponse := Hash( Hash(LA1) + ':' + FNonce + ':' + LResponse + Hash(LA2) ); {do not localize} LResult := 'Digest ' + {do not localize} 'username="' + Username + '", ' + {do not localize} 'realm="' + FRealm + '", ' + {do not localize} 'nonce="' + FNonce + '", ' + {do not localize} 'algorithm="' + FAlgorithm + '", ' + {do not localize} 'uri="' + FUri + '", '; LResult := LResult + 'qop="' + FQop + '", ' + {do not localize} 'nc=' + IntToHex(FNonceCount, 8) + ', ' + {do not localize} 'cnonce="' + LCNonce + '", '; {do not localize} LResult := LResult + 'response="' + LResponse + '"'; {do not localize} if FOpaque <> '' then begin LResult := LResult + ', opaque="' + FOpaque + '"'; {do not localize} end; Inc(FNonceCount); ARequest.AddAuthParameter(HTTP_HEADERFIELD_AUTH, LResult, TRESTRequestParameterKind.pkHTTPHEADER, [TRESTRequestParameterOption.poDoNotEncode]); end; procedure TDigestAuthenticator.ReadHeader(ARequest : TCustomRESTRequest); function Unquote(S: String): String; var I, Len: Integer; begin Result := S; Len := Length(Result); I := 2; // skip first quote while I <= Len do begin if Result[I] = '"' then begin Break; end; if Result[I] = '\' then begin Inc(I); end; Inc(I); end; Result := Copy(Result, 2, I-2); end; const AUTHVALUE = 'WWW-Authenticate'; DIGESTAUTH = 'Digest'; var S : String; begin FQopOptions.Clear; S := ARequest.Response.Headers.Values[AUTHVALUE]; if S.StartsWith(DIGESTAUTH) then begin S := Copy(S, Length(DIGESTAUTH) + 2); FQopOptions.CommaText := S; FRealm := UnQuote(FQopOptions.Values['realm']); FNonce := UnQuote(FQopOptions.Values['nonce']); FOpaque := UnQuote(FQopOptions.Values['opaque']); FQop := UnQuote(FQopOptions.Values['qop']); FAlgorithm := FQopOptions.Values['algorithm']; case ARequest.Method of rmPOST: FMethod := 'POST'; rmPUT: FMethod := 'PUT'; rmGET: FMethod := 'GET'; rmDELETE: FMethod := 'DELETE'; rmPATCH: FMethod := 'PATCH'; else raise ERESTException.Create('Unknown Method'); end; FUri := ARequest.GetFullRequestURL(); FUri := Copy(FUri, Pos('://', FUri) + 3); FUri := Copy(FUri, Pos('/', FUri)); end; end; procedure TDigestAuthenticator.SetPassword(const AValue: string); begin if (AValue <> FPassword) then begin FPassword := AValue; PropertyValueChanged; end; end; procedure TDigestAuthenticator.SetUsername(const AValue: string); begin if (AValue <> FUsername) then begin FUsername := AValue; PropertyValueChanged; end; end; { TDigestAuthenticatorAdapter } procedure TDigestAuthenticatorAdapter.AddFields; const sUserName = 'UserName'; sPassword = 'Password'; var LGetMemberObject: IGetMemberObject; begin CheckInactive; ClearFields; if Authenticator <> nil then begin LGetMemberObject := TBindSourceAdapterGetMemberObject.Create(Self); CreateReadWriteField<string>(sUserName, LGetMemberObject, TScopeMemberType.mtText, function: string begin result := Authenticator.Username; end, procedure(AValue: string) begin Authenticator.Username := AValue; end); CreateReadWriteField<string>(sPassword, LGetMemberObject, TScopeMemberType.mtText, function: string begin result := Authenticator.Password; end, procedure(AValue: string) begin Authenticator.Password := AValue; end); end; end; { TSubDigestAuthenticationBindSource } function TSubDigestAuthenticationBindSource.CreateAdapterT: TRESTAuthenticatorAdapter<TDigestAuthenticator>; begin result := TDigestAuthenticatorAdapter.Create(Self); end; end.
Delphi-Quellcode:
unit Main;
interface uses Winapi.Windows, Winapi.Messages, System.SysUtils, System.Variants, System.Classes, Vcl.Graphics, Vcl.Controls, Vcl.Forms, Vcl.Dialogs, Vcl.StdCtrls, REST.Client; type TMainForm = class(TForm) RequestButton: TButton; procedure RequestButtonClick(Sender: TObject); private { Private-Deklarationen } procedure CatchHttpProtocolError(Sender : TCustomRESTRequest); public { Public-Deklarationen } end; var MainForm: TMainForm; implementation {$R *.dfm} uses REST.Types, REST.Authenticator.Digest; procedure TMainForm.RequestButtonClick(Sender: TObject); var Client : TRestClient; Request : TRestRequest; Auth : TDigestAuthenticator; begin Client := TRestClient.Create('http://httpbin.org'); try Request := TRestRequest.Create(Client); Request.Resource := 'digest-auth/auth/test/user'; Request.OnHTTPProtocolError := CatchHttpProtocolError; Request.Execute; if Request.Response.StatusCode = 401 then begin Auth := TDigestAuthenticator.Create('test', 'user'); try Auth.Authenticate(Request); Request.Execute; finally Auth.Free; end; end; ShowMessage(Request.Response.Content); finally Client.Free; end; end; procedure TMainForm.CatchHttpProtocolError(Sender: TCustomRESTRequest); begin if Sender.Response.StatusCode <> 401 then begin raise ERESTException.Create(Sender.Response.Content); end; end; end.
Ibi fas ubi proxima merces
sudo /Developer/Library/uninstall-devtools --mode=all |
![]() |
Ansicht |
![]() |
![]() |
![]() |
ForumregelnEs ist dir nicht erlaubt, neue Themen zu verfassen.
Es ist dir nicht erlaubt, auf Beiträge zu antworten.
Es ist dir nicht erlaubt, Anhänge hochzuladen.
Es ist dir nicht erlaubt, deine Beiträge zu bearbeiten.
BB-Code ist an.
Smileys sind an.
[IMG] Code ist an.
HTML-Code ist aus. Trackbacks are an
Pingbacks are an
Refbacks are aus
|
|
Nützliche Links |
Heutige Beiträge |
Sitemap |
Suchen |
Code-Library |
Wer ist online |
Alle Foren als gelesen markieren |
Gehe zu... |
LinkBack |
![]() |
![]() |