Delphi-PRAXiS

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Netzwerke (https://www.delphipraxis.net/14-netzwerke/)
-   -   Delphi SOAP Login (einmalig) (https://www.delphipraxis.net/121691-soap-login-einmalig.html)

Heffalump 2. Okt 2008 14:56


SOAP Login (einmalig)
 
Hallo zusammen,

bin zur Zeit dabei einen Client zu schreiben, der per SOAP mit einm SAP Server kommunizieren soll. Eigentlich kein Problem. Versucht man alle möglichen bzw. in Frage kommenden RFCs in die WSDL Datei zu packen, dann wird das erstens unübersichtlich und zweitens tauchen immer wieder Funktionen auf, an die man nicht gedacht hat. Auch das ist kein Problem, ruft man halt verschiedene WSDL Dateien/Informationen ab. Schön nach Inhalt sortiert.

Mein Problem ist folgendes. Ich versuche derzeit eine Möglichkeit zu finden, einen zentralen Login mit Start des Programmes zu ermöglichen und an dieser Stelle bereits die Zugangsberechtigung zu prüfen. Leider geben das die SOAP Komponenten nicht her. Die Stellen eine Verbindung zum Server erst mit dem erstmaligen abrufen von Daten her und damit erfolgt auch erst zu diesem Zeitpunkt die Prüfung. Das ärgerlich ist, stimmen dann die Userangaben nicht, öffnet sich leider das Standard Windows Login (für I-Net Anwendungen). Das will ich natürlich nicht. Hat einer eine Idee?

MFG

Phoenix 2. Okt 2008 15:09

Re: SOAP Login (einmalig)
 
Leider keine Idee.. aber ich hab das gleiche Problem bei anderen Webservices.. wäre also auch sehr an einer Lösung interessiert ;-)

Phoenix 16. Okt 2008 20:14

Re: SOAP Login (einmalig)
 
Ich haaaaabs ;-)

Aaalso, folgendes:

Man muss dem WebService ein THttpRio Objekt mitgeben. Defaultmässig ist das nil und dann wird ein standard-Objekt verwendet.
Diesem selber erstellen THttpRio-Objekt (oder besser: dessem HttpWebNode) weisen wir einen Eventhandler zu, der ausgeführt wird, bevor der Webservice einen http-Request abschickt.

In diesem Eventhandler setzen wir auf dem aktuellen Request dann die nötigen Header für die Http Basic Authentication. Also Username & Passwort. Beispielhaft setze ich hier auch noch nen Timeout.

Achtung: Wenn Benutzername oder Kennwort falsch sind, und der Server einen 401 schickt, dann kommt der Dialog zumindest bei mir im Moment immer noch hoch. Ich weiss grad ned, wie ich den ausschalte. Aber zumindest initial kann man hiermit Benutzer und Kennwort setzen und somit den Dialog (sofern die Anmeldedaten richtig sind) unterdrücken.

Delphi-Quellcode:
uses
   SOAPHTTPClient, SOAPHTTPTrans, WinInet,

type
   TForm1 = class(TForm)
      btnConnectServer: TButton;
      edtUrl: TEdit;
      edtUser: TEdit;
      edtpassword: TEdit;
      procedure btnConnectServerClick(Sender: TObject);
      procedure FormClose(Sender: TObject; var Action: TCloseAction);
   private
      rio: THttpRio;
      rptSvc: ReportingService2005Soap; // das ist aktuell mein Webservice
      procedure HttpRioHttpWebNodeBeforePost(const HTTPReqResp: THTTPReqResp; Data: Pointer);
      { Private declarations }
   public
      { Public declarations }
   end;

implementation

procedure TForm1.HttpRioHttpWebNodeBeforePost(
   const HTTPReqResp: THTTPReqResp; Data: Pointer);
var TimeOut : integer;
begin
   TimeOut := 2000; // in milleseconds.
   if not InternetSetOption(Data,
         INTERNET_OPTION_RECEIVE_TIMEOUT,
         Pointer(@TimeOut),
         SizeOf(TimeOut)) then
   ShowMessage(SysErrorMessage(GetLastError));

   if not InternetSetOption(Data,
                      INTERNET_OPTION_USERNAME,
                      PChar(rio.HTTPWebNode.UserName),
                      Length(rio.HTTPWebNode.UserName)) then
       ShowMessage(SysErrorMessage(GetLastError));

   if not InternetSetOption(Data,
                      INTERNET_OPTION_PASSWORD,
                      PChar(rio.HTTPWebNode.Password),
                      Length (rio.HTTPWebNode.Password)) then
       ShowMessage(SysErrorMessage(GetLastError));
end;

// Aufräumen
procedure TForm1.FormClose(Sender: TObject; var Action: TCloseAction);
begin
   if Assigned(rptSvc) then
      rptSvc._Release();

   if Assigned(rio) then
      FreeAndNil(rio);
end;

procedure TForm1.btnConnectServerClick(Sender: TObject);
begin
   // Initialize additional params (like eventhandler for http basic authentication)
   if not Assigned(rio) then
   begin
      rio := THTTPRIO.Create(self);
      rio.HTTPWebNode.UserName := edtUser.Text;
      rio.HTTPWebNode.Password := edtpassword.Text;
      rio.HTTPWebNode.OnBeforePost := self.HttpRioHttpWebNodeBeforePost;
   end;

   // Create Web Service IDispatch interface with additional params here:
   if not assigned(rptSvc) then
   begin
      rptSvc := ReportService2005.GetReportingService2005Soap(false, edtUrl.Text, rio);
   end;

Meine Quellen waren:
http://shenoyatwork.blogspot.com/200...ter-break.html
http://shenoyatwork.blogspot.com/200...lphi-soap.html

Phoenix 2. Dez 2008 08:13

Re: SOAP Login (einmalig)
 
*nochmal ausgrab*

Okay... die Lösung aus meinen Quellen war für Delphi 7...
Jetzt darf ich die ganze Chause die ich eigentlich mal für Delphi 2009 / 2007 geschrieben habe nach Delphi 6 zurückportieren.

In Delphi 6 hat der HttpRio.HttpWebNode das OnBeforePost Event leider nicht.
Wie gehe ich da jetzt am besten vor, um das gleiche mit Delphi 6 zu schaffen?

Heffalump 2. Dez 2008 23:01

Re: SOAP Login (einmalig)
 
Hallo,

nun, ich nutze nicht das von Dir verwendete Ereignis, sondern das OnWinInetError. TConnection ist eine eigene Klasse, in der ich die Infos für Zugang zum Webservice und eventuellen Proxy speichere und zur Zurverfügungstellung der OnWinInetError Funktion.

Das gibt mir die Möglichkeit, das ich mit dem Start des Programmes bereits die entsprechenden Informationen abfragen kann und erst verwenden muss, wenn der Webserver/Proxy keine integrierte Authentifizierung unterstützt bzw. die Rechte nicht ausreichen. Sollten die Infos falsch sein, dann wird nicht der Standarddialog aufgerufen, sondern das Ereignis abgefangen und mit einem eigenen Dialog abgefragt.


Delphi-Quellcode:
function TConnection.OnWinInetError(LastError: LongWord;
  Request: Pointer): LongWord;
var P: Pointer;
    Status, Len, Index: LongWord; //DWord;

begin
  Len := SizeOf(Status);
  Index := 0;

HttpQueryInfo(Request, HTTP_QUERY_STATUS_CODE or HTTP_QUERY_FLAG_NUMBER,
    @Status, Len, Index);

case Status of
  HTTP_STATUS_DENIED :
    begin
      if Self._FirstAuthCall then
        begin
          InternetSetOption(Request,INTERNET_OPTION_USERNAME,@Self._UserName[1],System.Length(Self._UserName)*2);
          InternetSetOption(Request,INTERNET_OPTION_PASSWORD,@Self._UserPassword[1],System.Length(Self._UserPassword)*2);
          Self._FirstAuthCall := False;
          Result := ERROR_INTERNET_FORCE_RETRY;
        end
      else
        begin
          if Self.ShowWebServiceDialog then
            begin
            InternetSetOption(Request,INTERNET_OPTION_USERNAME,@Self._UserName[1],System.Length(Self._UserName)*2);
            InternetSetOption(Request,INTERNET_OPTION_PASSWORD,@Self._UserPassword[1],System.Length(Self._UserPassword)*2);
            Result := ERROR_INTERNET_FORCE_RETRY;
            end
          else Result := ERROR_CANCELLED;
        end;
    end;
  HTTP_STATUS_PROXY_AUTH_REQ :
    begin
      if Self._FirstProxyAuthCall then
        begin
          InternetSetOption(Request,INTERNET_OPTION_PROXY_USERNAME,@Self._ProxyUserName[1],System.Length(Self._ProxyUserName)*2);
          InternetSetOption(Request,INTERNET_OPTION_PROXY_PASSWORD,@Self._ProxyUserPassword[1],System.Length(Self._ProxyUserPassword)*2);
          Self._FirstProxyAuthCall := False;
          Result := ERROR_INTERNET_FORCE_RETRY;
        end
      else
        begin
          if Self.ShowProxyDialog then
            begin
            InternetSetOption(Request,INTERNET_OPTION_PROXY_USERNAME,@Self._ProxyUserName[1],System.Length(Self._ProxyUserName)*2);
            InternetSetOption(Request,INTERNET_OPTION_PROXY_PASSWORD,@Self._ProxyUserPassword[1],System.Length(Self._ProxyUserPassword)*2);
            Result := ERROR_INTERNET_FORCE_RETRY;
            end
          else Result := ERROR_CANCELLED;
        end;
    end;
  else
    begin
    Result := InternetErrorDlg(GetDesktopWindow(), Request, LastError,
                                     FLAGS_ERROR_UI_FILTER_FOR_ERRORS or
                                     FLAGS_ERROR_UI_FLAGS_CHANGE_OPTIONS or
                                     FLAGS_ERROR_UI_FLAGS_GENERATE_DATA, P);
    end;
  end;
end;


Alle Zeitangaben in WEZ +1. Es ist jetzt 19:02 Uhr.

Powered by vBulletin® Copyright ©2000 - 2024, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024 by Thomas Breitkreuz