Delphi-PRAXiS

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Netzwerke (https://www.delphipraxis.net/14-netzwerke/)
-   -   Delphi REST Request Fehler (https://www.delphipraxis.net/206599-rest-request-fehler.html)

t2000 11. Jan 2021 08:58

REST Request Fehler
 
Hallo Leute,

ich habe ein dringendes Problem bei einem Kunden.

Eine ERST Abfrage an einen WordPress / WooCommerce Shop schlägt fehl. Es ist bei uns die erste Anfrage an den Shop (innerhalb der Anwendung), daher vermute ich, dass auch alle anderen fehlschlagen würden.
Das Programm läuft bei mir auf meinem Entwicklungsrechner einwandfrei, aber auf dem Kundenserver nicht.

Die Fehlermeldung lautet:
(ist eine Exception bei RESTRequest.Execute)

REST-Anforderung fehlgeschlagen: Fehler beim Senden der Daten: (12175) Es ist ein Sicherheitsfehler aufgetreten

Method: rmGet
Ressource: products/categories?per_page=100
Suffix: <leer>

BasicAuth (WooCommercevorgabe)

Mein PC ist Windows 10 Enterprise (aktuelles Update)
Kunden-PC (leider noch) Windows Server 2008 R2

Der neue Server ist in Arbeit, wird aber wohl erst Feb/März in Betrieb gehen

Die gleiche REST Anforderung über Google Chrome mit dem Tool REST-ED funktioniert. Auch auf dem Kunden-PC
Wenn ich aber mit Google Chrome den online (!) Postman nutze, gibt der eine Fehlermeldung, dass hier CORS nicht unterstützt wird und ich die Desktop App nehmen soll.

Das ist die aktuelle Situation. Ich sollte eigentlich die Anbindung an den Shop heute vormittag fertig installiert haben. Wie gesagt, bei mir im Büro läuft alles einwandfrei.
Hat jemand ein Idee, wo ich weiter suchen könnte?

EInfach nur Ideen, wo ich suchen und testen könnte.

Danke.

sh17 11. Jan 2021 09:07

AW: Dingend! REST Request Fehler
 
Dann probiere es doch mal mit der Postman Desktop Version!

Ansonsten bau den Request mal von Hand mit Indy oder so

t2000 11. Jan 2021 09:07

AW: Dingend! REST Request Fehler
 
Kann das was mit den RestClient.SecureProtocols zu tun haben?

Wenn ja, welche muss ich setzen? Alle?
Stanbdard sind alle auf False

t2000 11. Jan 2021 09:08

AW: Dingend! REST Request Fehler
 
Zitat:

Zitat von sh17 (Beitrag 1480722)
Dann probiere es doch mal mit der Postman Desktop Version!

Programme auf Kunden-PC's installieren ist immer so eine Sache. Müsste dazu erst den Administrator erreichen.

Rollo62 11. Jan 2021 09:26

AW: Dingend! REST Request Fehler
 
Kann es am Wordpress selber liegen, da war doch vor kurzem etwas in der Presse dass die REST-Schnittstelle Sicherheitslücken hat, und dass man die besser deaktiviert.
Ich weiss nicht ob Du den Wordpress-Server selber hostest, oder ob das jemand abgeschaltet haben könnte.

t2000 11. Jan 2021 09:41

AW: Dingend! REST Request Fehler
 
Zitat:

Zitat von Rollo62 (Beitrag 1480729)
Kann es am Wordpress selber liegen, da war doch vor kurzem etwas in der Presse dass die REST-Schnittstelle Sicherheitslücken hat, und dass man die besser deaktiviert.
Ich weiss nicht ob Du den Wordpress-Server selber hostest, oder ob das jemand abgeschaltet haben könnte.

Nein. Es gibt WordPress REST und WooCommerce REST. Das WordPress brauchen wir für den Bilder (Medien) Upload. Für den Shop reicht WooCommerce aus.
Wir hosten selber.
UND, von meinem PC läuft alles einwandfrei.
UND, beim Kunden läuft die Abfrage, wenn ich mit Chrome und REST Editor arbeite.

Nur mit meinem Delphi 10.4.1 Programm geht es nicht. (Beim Kunden!)

t2000 11. Jan 2021 09:43

AW: Dingend! REST Request Fehler
 
Alle Varianten von RestClient.SecureProtocols getestet. Nichts geht.

TiGü 11. Jan 2021 09:46

AW: Dingend! REST Request Fehler
 
Unterstützt die von dir verwendete Delphi-Version (vermutlich Sydney) überhaupt dieses alte Betriebssystem?
Meine Frage zielt darauf ab:
Gibt es überhaupt die von den Delphi-REST-Komponenten erforderten Schnittstellen, Funktionen, DLLs etc. etc. in dieser Windows-Version?

Mir liegen nur die Quelltexte von Tokyo vor, aber im Prinzip wird für jeden Execute-Aufruf vom RESTRequest eine Instanz von TWinHTTPRequest erzeugt (System.Net.HttpClient.Win).
Wenn die hier eingebauten Windows-Funktionen wie bspw. WinHttpConnect, WinHttpOpenRequest, WinHttpAddRequestHeaders oder WinHttpSetTimeouts nicht in Windows Server 2008 vorliegen oder andere Werte erwarten bzw. zurück liefern, dann schlägt das natürlich fehl.

Daniel 11. Jan 2021 09:59

AW: REST Request Fehler
 
Kann das ein Problem mit der TLS-Version sein?
Der 2008er-Server ist womöglich nicht ganz up-to-date was TLS 1.2/1.3 angeht. Wenn nun also der Webserver etwas fordert, was besagter Windows-Server nicht kann, wäre das eine plausible Erklärung.
Zu prüfen wäre, was dieser Windows 2008er-Server für Verschlüsselungen für HTTP anbietet (SSL / TLS und die jeweiligen Versionen). Und das müsste dann mit dem Webserver abgeglichen werden, was der seinerseits an Anforderungen stellt.

t2000 11. Jan 2021 10:29

AW: REST Request Fehler
 
Der Server hat in den Internetoptionen TLS 1.0/1.1/1.2
Ich habe im RESTClient jetzt TLS 1.1/1.2 eingestellt.
Geht aber nicht.

Wäre super, wenn ich noch ne Lösung finden würde. Aber zwischenzeitlich muss ich nun beim Kunden das Programm auf einen anderen PC installieren, bis ich die Lösung für den Server habe oder der Techniker den neuen Server (vielleicht schon früher) fertig hat.

TiGü 11. Jan 2021 13:32

AW: REST Request Fehler
 
Debuggen vor Ort bzw. Remote Debugging ist drin?

sh17 11. Jan 2021 13:44

AW: REST Request Fehler
 
Windows Server 2008 R2 - auch wenns blöd klingt, aber irgendwann ist eben auch mal Ende der Fahnenstange. Ich hatte letztens
einen Windows Server 2003, hab ich direkt abgelehnt, auch wenn es evtl. funktioniert hätte

Ist das die erste Version, die auf dem System laufen soll? Oder ist das nur ein Update und vorher ging schon mal alles?

t2000 11. Jan 2021 14:02

AW: REST Request Fehler
 
Unsere Software läuft da schon seit über 10 Jahren. Hier ging es um ein separates Programm, welchses Daten in einen Woocommerce Shop schieben soll.
Ich hatte auch schon Herbst gesagt, dass wir seit Anfang 2020 jeglichen Support für Win 7 und Windows Server 2008 ablehnen.
Ist aber ein sehr guter Kunde und der Techniker hat versprochen bis Februar einen neuen Server zu liefern.

Leider sollte wegen Corona jetzt der Shop vorzeit aktiviert werden. Hätte ja klappen können.
So wie es aussieht, werden wir das Transfermodul einfach auf einem "normalen" Win10 PC im Netzwerk laufen lassen. Die Daten können ja auch über's Netz aus dem SQL-Server geladen werden um sie dann ins Internet zu stellen.

Ich sehe zur Zeit keine andere Lösung. Das letzte Update auf dem Server war auch im Mai 2018 !! Ich lass da jetzt die Finger von.

Danke für eure Bemühungen

jaenicke 11. Jan 2021 14:15

AW: REST Request Fehler
 
Man sollte nicht vergessen, dass der TRestClient die Verschlüsselung über das Betriebssystem erledigt. Deshalb muss man an der Stelle schauen, ob das Betriebssystem auch die nötigen Protokolle kennt. Für Server 2008 R2 muss das Service Pack 1 installiert sein und die Protokolle müssen aktiviert sein:
https://support.microsoft.com/de-de/...rotocols-in-wi

TiGü 11. Jan 2021 14:19

AW: REST Request Fehler
 
Wie oben beschrieben, habe ich nur die Tokyo-Sourcen vorliegen.
Ich nehme an, da hat sich zwei Versionen weiter schon was getan.

Ich vermute, dass du den Fehler in TWinHTTPClient.DoExecuteRequest bekommst.
Also beim Senden des Requests mit WinHttpSendRequest.

Das ist in Tokyo wie folgt gelöst (Zeile 855 ff. aus System.Net.HttpClient.Win):

Delphi-Quellcode:
  // Send Request
  LRes := WinHttpSendRequest(LRequest.FWRequest, WINHTTP_NO_ADDITIONAL_HEADERS, 0, WINHTTP_NO_REQUEST_DATA, 0, LDataLength, 0);
  if not LRes then
  begin
    LastError := GetLastError;
    case LastError of
      ERROR_WINHTTP_SECURE_FAILURE:
        Exit(TExecutionResult.ServerCertificateInvalid);
      ERROR_WINHTTP_CLIENT_AUTH_CERT_NEEDED:
        Exit(TExecutionResult.ClientCertificateNeeded);
      else
        raise ENetHTTPClientException.CreateResFmt(@SNetHttpClientSendError, [GetLastError, SysErrorMessage(GetLastError, GLib.Handle)]);
    end;
  end;
Vom Fehlertext her, bekommst du ja einen ERROR_WINHTTP_SECURE_FAILURE ("Es ist ein Sicherheitsfehler aufgetreten").
Das wurde hier in 10.2 Tokyo noch mit einem einfachen Enum-Wert als Rückgabe gelöst.

Ich könnte mir vorstellen, dass dies in 10.4 Sydney auf den ENetHTTPClientException.CreateResFmt geht.
Denn
Delphi-Quellcode:
SNetHttpClientSendError = 'Fehler beim Senden der Daten: (%d) %s';
ist der mittlere Teil deiner Fehlermeldung.
Der vordere Teil (sRESTRequestFailed) kommt aus dem except-Block von TCustomRESTRequest.Execute (Rest.Client),
Delphi-Quellcode:
        // Unknown error, might even be on the client side. raise it!
        on E: Exception do
        begin
          // If Execute raises an Exception, then the developer should have look into the actual BaseException
          raise ERESTException.CreateFmt(sRESTRequestFailed, [E.Message]);
        end;
Wie dem auch sein, für ERROR_WINHTTP_SECURE_FAILURE sagt die MSDN (https://docs.microsoft.com/en-us/win...psendrequest):
Zitat:

One or more errors were found in the Secure Sockets Layer (SSL) certificate sent by the server.
To determine what type of error was encountered, verify through a WINHTTP_CALLBACK_STATUS_SECURE_FAILURE notification in a status callback function.
For more information, see WINHTTP_STATUS_CALLBACK.
Was uns hierzu führt: https://docs.microsoft.com/en-us/win...tatus_callback
Du könntest also durch das setzen einer Callback mehr Information erhalten, warum es bei dir scheitert (via WinHttpSetStatusCallback -> https://docs.microsoft.com/en-us/win...statuscallback).

In Tokyo ist dafür nichts vorgesehen bzw. ist das in TWinHTTPClient.Create auskommentiert.
Entweder gibt es in Sydney dann Möglichkeiten dafür ODER du kopierst dir die System.Net.HttpClient.Win in dein Projekt und veränderst sie entsprechend, um mehr Informationen loggen zu können.

TiGü 11. Jan 2021 15:04

AW: REST Request Fehler
 
Meine obige Idee noch schnell skizziert. Wie geschrieben die System.Net.HttpClient.Win Unit kopieren und dem eigenen Projekt hinzufügen, um Änderungen vornehmen zu können:

Delphi-Quellcode:
procedure HTTPCallback(hInternet: HINTERNET; dwContext: Pointer; dwInternetStatus: DWORD;
    lpvStatusInformation: Pointer; dwStatusInformationLength: DWORD); stdcall;
var
//  LRequest: TWinHTTPRequest;
  StatusFlags: DWORD;
  Flag: DWORD;

  function FlagToString(Flag: DWORD): string;
  begin
    case Flag of
       WINHTTP_CALLBACK_STATUS_FLAG_CERT_REV_FAILED : Result := 'CERT_REV_FAILED';
       WINHTTP_CALLBACK_STATUS_FLAG_INVALID_CERT : Result := 'INVALID_CERT';
       WINHTTP_CALLBACK_STATUS_FLAG_CERT_REVOKED : Result := 'CERT_REVOKED';
       WINHTTP_CALLBACK_STATUS_FLAG_INVALID_CA : Result := 'INVALID_CA';
       WINHTTP_CALLBACK_STATUS_FLAG_CERT_CN_INVALID : Result := 'CERT_CN_INVALID';
       WINHTTP_CALLBACK_STATUS_FLAG_CERT_DATE_INVALID : Result := 'CERT_DATE_INVALID';
       WINHTTP_CALLBACK_STATUS_FLAG_CERT_WRONG_USAGE : Result := 'CERT_WRONG_USAGE';
       WINHTTP_CALLBACK_STATUS_FLAG_SECURITY_CHANNEL_ERROR : Result := 'SECURITY_CHANNEL_ERROR';
    end;
  end;

  procedure CheckFlags(Value, Flag: DWORD);
  begin
    if (Value and Flag) = Flag then
      Writeln(Flag.ToHexString, Format(' %s is in lpvStatusInformation', [FlagToString(Flag)]));
  end;

begin
  AllocConsole;
  case dwInternetStatus of
    WINHTTP_CALLBACK_STATUS_SECURE_FAILURE:
    begin
//      LRequest := TWinHTTPRequest(dwContext);
      StatusFlags := PDWORD(lpvStatusInformation)^;

      CheckFlags(StatusFlags, WINHTTP_CALLBACK_STATUS_FLAG_CERT_REV_FAILED);
      CheckFlags(StatusFlags, WINHTTP_CALLBACK_STATUS_FLAG_INVALID_CERT);
      CheckFlags(StatusFlags, WINHTTP_CALLBACK_STATUS_FLAG_CERT_REVOKED);
      CheckFlags(StatusFlags, WINHTTP_CALLBACK_STATUS_FLAG_INVALID_CA);
      CheckFlags(StatusFlags, WINHTTP_CALLBACK_STATUS_FLAG_CERT_CN_INVALID);
      CheckFlags(StatusFlags, WINHTTP_CALLBACK_STATUS_FLAG_CERT_DATE_INVALID);
      CheckFlags(StatusFlags, WINHTTP_CALLBACK_STATUS_FLAG_CERT_WRONG_USAGE);
      CheckFlags(StatusFlags, WINHTTP_CALLBACK_STATUS_FLAG_SECURITY_CHANNEL_ERROR);
    end;
  end;
end;

constructor TWinHTTPClient.Create;
begin
  inherited Initializer;

  FWinCertList := TList<PCCERT_CONTEXT>.Create;
  FCertificateList := TList<TCertificate>.Create;

  GLib.LockHandleGC;
  FWSession := WinHttpOpen('', WINHTTP_ACCESS_TYPE_NO_PROXY, WINHTTP_NO_PROXY_NAME, WINHTTP_NO_PROXY_BYPASS, 0);
  if FWSession = nil then
    raise ENetHTTPClientException.CreateRes(@SNetHttpClientHandleError);

  WinHttpSetStatusCallback(FWSession, HTTPCallback, WINHTTP_CALLBACK_STATUS_SECURE_FAILURE, 0); // das ist neu!
end;
Statt einer Console kann natürlich ein beliebiger anderer Logging-Mechanismus verwendet werden.

jaenicke 11. Jan 2021 15:04

AW: REST Request Fehler
 
Zitat:

Zitat von TiGü (Beitrag 1480770)
In Tokyo ist dafür nichts vorgesehen bzw. ist das in TWinHTTPClient.Create auskommentiert.
Entweder gibt es in Sydney dann Möglichkeiten dafür ODER du kopierst dir die System.Net.HttpClient.Win in dein Projekt und veränderst sie entsprechend, um mehr Informationen loggen zu können.

Das wurde mit Delphi 10.3 überarbeitet. Dort gibt es nun ein entsprechendes Callback, das die Auswertung übernimmt und in der Property SecureFailureReasons ablegt.

Es wurden auch diverse Routinen zur Auswertung von Zertifikaten usw. hinzugefügt.

// EDIT:
Ja, so ähnlich sieht die Callbackfunktion HTTPCallback auch in der RTL nun aus.

t2000 11. Jan 2021 15:28

AW: REST Request Fehler
 
Ja, in 10.4.1 so:

in System.Net.HttpClient.Win
Delphi-Quellcode:
  // Send Request
  if not WinHttpSendRequest(LRequest.FWRequest, WINHTTP_NO_ADDITIONAL_HEADERS, 0, WINHTTP_NO_REQUEST_DATA, 0, LDataLength, 0) then
    Exit(HandleExecuteError(@SNetHttpClientSendError, ARequest));
und dann:

Delphi-Quellcode:
function TWinHTTPClient.HandleExecuteError(AErrorMsg: PResStringRec; const ARequest: THTTPRequest): TWinHTTPClient.TExecutionResult;
var
  LastError: Cardinal;
begin
  LastError := GetLastError;
  case LastError of
    ERROR_WINHTTP_SECURE_FAILURE:
      if (SecureFailureReasons <> [THTTPSecureFailureReason.SecurityChannelError]) and
         not TWinHTTPRequest(ARequest).FServerCertificateAccepted then
        Exit(TExecutionResult.ServerCertificateInvalid)
      else
        raise ENetHTTPClientException.CreateResFmt(AErrorMsg, [LastError, SysErrorMessage(LastError, TWinHttpLib.Handle)]);
    ERROR_WINHTTP_CLIENT_AUTH_CERT_NEEDED:
      Exit(TExecutionResult.ClientCertificateNeeded);
    ERROR_WINHTTP_RESEND_REQUEST:
      Exit(TExecutionResult.Retry);
    else
      if (LastError = ERROR_WINHTTP_OPERATION_CANCELLED) and
         (SecureFailureReasons = [THTTPSecureFailureReason.CertNotAccepted]) then
        raise ENetHTTPCertificateException.CreateRes(@SNetHttpServerCertificateNotAccepted)
      else
      if (LastError = ERROR_WINHTTP_OPERATION_CANCELLED) or TWinHTTPRequest(ARequest).FCancelled then
        Exit(TExecutionResult.Success)
      else
        raise ENetHTTPClientException.CreateResFmt(AErrorMsg, [LastError, SysErrorMessage(LastError, TWinHttpLib.Handle)]);
  end;
end;
Ich habe nun aber erstmal damit zu tun, dass über das Provisorium die Daten alle rüber kommen. Dauert ein wenig. Danach spreche ich mit dem Kunden, ob dasa Provisorium noch 6 Wochen laufen oder wir weiter suchen sollen. Kostet ja alles Geld.

Vielen Dank nochmal, falls ich die Tage etwas Zeit habe, mache ich mir ein Testprogramm.

t2000 21. Jan 2024 15:10

AW: REST Request Fehler
 
Liste der Anhänge anzeigen (Anzahl: 2)
Wir hatten das Problem gerade wieder.

REST Abfrage auf Woocommerce Shop mit original Delphi Komponenten.
Gleichzeitig auf mehreren PC's.
Nur auf einem Windows 11 PC hat alles nach wie vor funktioniert.

Grund war folgender:
Auf dem Webserver, auf dem der Woocommerce Shop installiert ist, wurden verschiedene Updates eingespielt.
Anschließend einige Einstellungen überprüft. U.a. auch die SSL/TLS Einstellungen vom Server. Diese sollten regelmäßig synchronisiert werden.
Warum auch immer, die Einstellungen standen auf "modern". Das bedeutet, das nur TLS 1.3 erlaubt ist.

Unsere Testsystem auf Clientseite waren folgende:
Windows Server 2012 R2
Windows Server 2019
Windows 10
Windows 11

Das Programm, welches den REST Aufruf macht, war von 2021 und mit Delphi 10.4.1 kompiliert.
Gleichzeitig haben wir aber auch eine Version ganz neu mit Delphi 11.3 kompiliert und auch getestet.
Schon mal vorweg, es gab keinerlei Unterschiede zwischen der 2021er Version und heute.

Von den 4 Testsystemen lief nur Windows 11. Die 3 anderen System haben die Fehlermeldung gebracht.

Nun haben wir den Webserver auf "ausgewogen" gestellt. Also die mittlere Einstellung. Bei der ist TLS 1.2 und TLS 1.3 aktiv.

Gleiches Spiel auf allen 4 Testsystemen.

Nächster Test, Webserver auf "alt" eingestellt. Jetzt sind TLS 1.0 - TLS 1.3 verfügbar.

Alle System laufen wieder.
Egal ob in 2021 kompiliert oder aktuell.

Daneben haben wir natürlich verschieden Tests mit Einstellungen auf den Client PC's gemacht.
1) PC Internetoptionen verschieden Einstellungen TLS ausprpbiert
2) Delphi REST-Client Komponente Security Einstellung TLS 1.0 - 1.3 ausprobiert.

All das hat überhaupt keine Auswirkung gehabt.

Was bewirken die Einstellungen auf dem PC?
Was bewirken die Einstellungen in der REST Client Komponente?

Wie sind die zu nutzen?

Ich glaube, ich habe hier noch einige Wissenslücken.

Ich würde gerne den Webserver zumindest auf TLS 1.2 stellen ("ausgewogen"). Aber das bekomme ich nicht zum laufen.

Hier noch 2 Bilder von den PLESK Einstellungen auf dem Webserver.

Vielleicht hat ja noch mal jemand eine Idee.

Danke.
Viele Grüße
Thomas


https://www.delphipraxis.net/attachm...1&d=1705849501
https://www.delphipraxis.net/attachm...1&d=1705849524


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