Delphi-PRAXiS

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Netzwerke (https://www.delphipraxis.net/14-netzwerke/)
-   -   Webservice + SSL + D2010 (https://www.delphipraxis.net/162884-webservice-ssl-d2010.html)

mcbain 8. Sep 2011 15:00

Webservice + SSL + D2010
 
Hallo,
ich versuche gerade einen Webservice über HTTPS zu konsumieren. Leider funktioniert es nicht.

Ich nutze dafür eigentlich nur die HTTPClient Komponente.
Hier ein Beispiel welches problemlos funktioniert:

Code:

function TForm2.SendRequest(): string;
var err, str: string;
    req: TStringStream;
    strings: TStringList;
begin
try
 
    strings := TStringList.Create;
    XMlDoc.XML.LoadFromFile('weather.xml');
    strings.AddStrings(XMlDoc.XML);

    HttpClient.Request.URL := 'http://www.webservicex.net/WeatherForecast.asmx';
    HttpClient.Request.Accept := 'text/html, image/gif, image/jpeg, *; q=.2, */*; q=.2';
    HttpClient.Request.ContentType := 'application/soap+xml;charset=iso-8859-1;action="urn:sendblabla"';
    req := TStringStream.Create(strings.GetText);

    try
      str := HttpClient.Post(HttpClient.Request.URL , req);

    except
      On E: EIdHTTPProtocolException do
      begin
        err := 'HTTP-Fehler: ' + E.Message;
        str := E.ErrorMessage;
      end;
      On E: Exception do
        err := 'Allgemeiner Fehler: ' + E.Message;
    end;
finally
  strings.free;
end;
  Result := str;
end;
Hier der request in weather.xml:
Code:
<?xml version='1.0' encoding='iso-8859-1'?>
<soapenv:Envelope xmlns:soapenv="http://www.w3.org/2003/05/soap-envelope" xmlns:web="http://www.webservicex.net">
   <soapenv:Header/>   
   <soapenv:Body>
      <web:GetWeatherByPlaceName>
         <web:PlaceName>London</web:PlaceName>
      </web:GetWeatherByPlaceName>      
   </soapenv:Body>
</soapenv:Envelope>

Nutze ich nun fast den selben Code für einen HTTPS Webservice bekomme ich immer die Fehlermeldung Soecketerror #0:
Mein Code dafür sieht so aus:

Code:
var err, str: string;
    req: TStringStream;
    strings, header: TStringList;
    SSLIOHandler: TIdSSLIOHandlerSocketOpenSSL;

begin
try
    SSLIOHandler := TIdSSLIOHandlerSocketOpenSSL.Create(self);
    with SSLIOHandler do
    begin
      SSLOptions.Mode := sslmClient;
      SSLOptions.Method := sslvSSLv3;
      SSLOptions.VerifyMode := [];
      SSLOptions.VerifyDepth := 0;

    end;
     HttpClient.IOHandler := SSLIOHandler;

    header := TStringList.Create;
    header.LoadFromFile('header.txt');
    HttpClient.Request.RawHeaders.Assign(header);

    strings := TStringList.Create;
    XmlDoc.XML.LoadFromFile('hsst.xml');
    strings.AddStrings(XmlDoc.XML);

    HttpClient.BoundPort := 443;

    HttpClient.Request.URL := 'https://******************/webservice/********Service';
    HttpClient.Request.Accept := 'text/html, image/gif, image/jpeg, *; q=.2, */*; q=.2';
    HttpClient.Request.ContentType := 'application/soap+xml;charset=iso-8859-1;action="urn:sendBlabla"';

    req := TStringStream.Create(strings.GetText);

    str := HttpClient.Post(HttpClient.Request.URL , req);


except
      On E: EIdHTTPProtocolException do
      begin
        err := 'HTTP-Fehler: ' + E.Message;
        str := E.ErrorMessage;
      end;
      On E: Exception do
        err := 'Allgemeiner Fehler: ' + E.Message;


end;

   strings.free;
   header.Free;
   SSLIOHandler.Free;
   mmo2.Text := str;
end;
Die header.txt sieht so aus:
Code:
POST https://********/webservice/*********** HTTP/1.1
Content-type: text/xml;charset="utf-8"
Authorization: Basic ***************==
Soapaction: "http://***********.de/abrufen*****"
Accept: text/xml, multipart/related, text/html, image/gif, image/jpeg, *; q=.2, */*; q=.2
Host: **********:443
Connection: keep-alive
Content-Length: 719
Anzumerken ist noch, dass der Webservice http Basic Authentifizierung erfordert, deshalb wurde in der header.txt auch Autorization base64 codiert.
Die hsst.xml beinhaltet hier die Soap-Nachricht, jedoch stimmt diese 100%, deshalb liste ich diese mal hier nicht auf.

Hat jemand einen Rat warum es nicht funktioniert? Muss ich bei SSL und Webservices noch etwas beachten?

Das interessante ist, dass ich den Service mit dem Tool SoapUI proplemlos nutzen kann.
Ich weiß ist etwas viel, aber sitz jetzt schon 2 Tage dran und komm nicht mehr weiter.

Wäre nett, wenn mir jemand helfen könnte.
Vielen Dank.
mc

geskill 8. Sep 2011 16:17

AW: Webservice + SSL + D2010
 
Hey mcbain,
sieht soweit vernünftig aus, welche Indy Version benutzt du denn? Etwa die die mit Delphi 2010 mitinstalliert wurde? Im EDN gibt es dazu ein Thread mit dem gleichen Fehler wie bei dir, kannst es dann ja mal mit einem Indy-Update probieren: https://forums.codegear.com/message....ssageID=124091

Dies kannst du eigentlich weglassen:
Delphi-Quellcode:
     with SSLIOHandler do
     begin
       SSLOptions.Mode := sslmClient;
       SSLOptions.Method := sslvSSLv3;
       SSLOptions.VerifyMode := [];
       SSLOptions.VerifyDepth := 0;
     end;
Hier würde ich statt RawHeaders lieber CustomHeaders nehmen:
Delphi-Quellcode:
HttpClient.Request.RawHeaders.Assign(header);


hsst.xml kannst du auch direkt in den req:TStringStream laden :wink:

Grüße

mcbain 9. Sep 2011 11:14

AW: Webservice + SSL + D2010
 
Hallo Sebastian,
vielen Dank für deinen Tip.
Ich habe die aktuelle Indy10 nun installiert und der Fehler ist weg.

Jetzt habe ich nur noch das Problem, dass ich keine richtige Antwort vom Server bekomme. Ich bekomme keine XML Datei zurückgeschickt sondern HTML in dem steht
"<h2>Es ist ein allgemeiner Fehler aufgetreten!</h2>
<p>Leider kann Ihre Anfrage zur Zeit nicht bearbeitet werden. </p>"

Das verstehe ich aber nicht, ich rufe in dem Tool SoapUI genau die gleiche URL auf wie in meinem httpclient.request.url property.
Muss ich evtl. noch etwas mit dem Zertifikat anstellen?

Wäre super, wenn du mir weiterhelfen könntest nochmal.
Vielen Dank.
mc

geskill 9. Sep 2011 11:54

AW: Webservice + SSL + D2010
 
Die Fehlermeldung kommt meiner Meinung nach durch 2 mögliche Fehlerquellen zustande. Entweder du sendest die Daten nicht richtig oder der Server/Script blockt dich weil es dich als Client nicht mag :wink:

Die einfachste Möglichkeit wäre den Datenverkehr von SoapUI zum Server mittels WireShark aufzunehmen und mit einer 2ten Instanz von WireShark den Verkehr von deinem Tool zum Server so weißt du nachher genau, was das andere Tool sendet, damit es klappt. Das dumme ist nur ich sehe gerade das ganze wird per HTTPS abgewickelt, da wirst du dann leider nicht so viel auslesen können :P Da muss man schon nach Fiddler greifen und ein gefaktes SSL Zertifikat in den Zertifikatsspeicher laden. Ist mit ein bisschen "fummelarbeit" verbunden, besonders nachher das aufräumen aber es geht auch und du kannst dir sicher sein, dass du zu 100% die Lösung bekommst.

mcbain 9. Sep 2011 12:29

AW: Webservice + SSL + D2010
 
Ein gefaktes Zertifikat? In der Richtung habe ich noch nie etwas gemacht. Kannst du mir evtl. noch ein bisschen auf die Sprünge helfen?
Sorry, hab aber noch nicht so viel mit HTTPS realisiert.

geskill 9. Sep 2011 18:06

AW: Webservice + SSL + D2010
 
Wenn du dieses Fiddler installierst, dann gibt es in den Einstellungen einen Punkt, wo du dann draufklicken kannst und es wird ziemlich vollautomatisch ein gefaktes SSL Zertifikat installiert. Damit kann dann die Verbindung mitgeschnitten werden, da dafür dieses SSL Zertifikat benutzt wird. Jedoch wird Windows dir eingehend davon abraten.
Außerdem könntest du Probleme bekommen, wenn du am PC noch anderen Netzwerkaktivitäten wie normales Surfen und sowas wie ICQ am laufen hast. Nachher solltest du auch nochmal überprüfen ob das SSL-Zertifikat wieder sauber deinstalliert wurde. Wenn es nicht allzuviel Mühe macht würde ich fast sagen nimm' eine VM dafür.

mcbain 12. Sep 2011 08:05

AW: Webservice + SSL + D2010
 
So, habe nun Fiddler mal installiert und HTTPS Decrypt aktiviert.
Leider kapier ich nicht ganz, wo mir jetzt nun der genaue Traffic angezeigt wird.
Ich kann mit dem ResponseBuilder eine Anfrage erfolgreich absetzen, wie mit dem SoapUI Tool.
Aber wie sehe ich jetzt genau was mein Delphi Programm absetzt und was Fiddler absetzt? Lasse ich mein Delphi Programm ablaufen zeichnet Fiddler nämlich nichts auf, obwohl es auf "Capture" steht.

Es kann doch nur noch ein kleines Problem sein...
Wäre super, wenn du mir nochmal helfen könntest.
Vielen Dank.

mcbain 14. Sep 2011 09:26

AW: Webservice + SSL + D2010
 
So, ich habe nun eine Lösung für mein Problem gefunden.
Ich habe nun ganz auf die Indy-Komponenten verzichtet. Die einzige Komponente ist ein HTTPRio.

Hier der Code:

Code:
...
uses ... Rio, SOAPHTTPClient, WinInet , SOAPHttpTrans, EncdDecd, ...
...

procedure TForm2.rioHTTPWebNode1BeforePost(const HTTPReqResp: THTTPReqResp; //Fügt den benötigten HTTP-Header hinzu für die Basic-Authentication
  Data: Pointer);
var
  S: String;
begin
  S := 'Authorization: Basic **************==';               //HTTP-Basic-Authorization-Header
  HttpAddRequestHeaders(Data, PChar(S), Length(S), HTTP_ADDREQ_FLAG_ADD);

end;


procedure TForm2.Button1Click(Sender: TObject);
var request, response: TStringStream;
    strings: TStringList;
    str: string;
    recieveID: integer;
begin
  rio.HTTPWebNode.URL := 'https://********************/webservice/***************Service';    //URL des Webservices
  rio.HTTPWebNode.SoapAction := 'http://**************/abrufen*************************';  //URL der aufzurufenden Methode
  rio.HTTPWebNode.Agent := 'Mozilla';
  rio.Port := '443';

  try

    strings := TStringList.Create;
    strings.LoadFromFile('request.xml');  //Hier ist der XML-request enthalten
 
    request := TStringStream.Create(strings.GetText);
    response := TStringStream.Create('');

    recieveID := rio.HTTPWebNode.Send(request);           //Request

    rio.HTTPWebNode.Receive(recieveID,response,false);    //Response
 
    response.Position := 0;
    mmo2.Lines.LoadFromStream(response, TEncoding.UTF8);

  finally
     strings.Free;
     request.Free;
     response.Free;
  end;

end;
Als kleine Anmerkung, in der Unit EncdDecd sind Funktionen für die Base64 Kodierung/Enkodierung enthalten. Damit kann man für HTTP Autorization Header den Usernamen und Passwort umwandeln.

Ich hoffe, ich konnte jemandem damit helfen.

Vielen Dank an Sebastian.


Alle Zeitangaben in WEZ +1. Es ist jetzt 05:17 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