AGB  ·  Datenschutz  ·  Impressum  







Anmelden
Nützliche Links
Registrieren
Zurück Delphi-PRAXiS Programmierung allgemein Netzwerke Probleme mit SOAP von 10.2.3 nach 10.3.1
Thema durchsuchen
Ansicht
Themen-Optionen

Probleme mit SOAP von 10.2.3 nach 10.3.1

Ein Thema von Bbommel · begonnen am 9. Aug 2019 · letzter Beitrag vom 13. Sep 2019
Antwort Antwort
Bbommel

Registriert seit: 27. Jun 2007
Ort: Köln
672 Beiträge
 
Delphi 12 Athens
 
#1

AW: Probleme mit SOAP von 10.2.3 nach 10.3.1

  Alt 4. Sep 2019, 13:20
Gerade erst gemerkt: kann vielleicht mal ein Mod den Titel des Themas von "REST" nach "SOAP" ändern? Ich Dödel.
  Mit Zitat antworten Zitat
Bbommel

Registriert seit: 27. Jun 2007
Ort: Köln
672 Beiträge
 
Delphi 12 Athens
 
#2

AW: Probleme mit SOAP von 10.2.3 nach 10.3.1

  Alt 12. Sep 2019, 11:40
Vorweg die Bitte an einen Moderator: kann einer von euch Mods das Thema von "REST" nach "SOAP" umbenennen, damit es auch von anderen korrekt gefunden wird? Ich hatte damals beim Erstellen offenbar einen kleinen Aussetzer.

Ich habe die Lösung für das Problem. Leider ist es auch in Delphi Rio 10.3.2 noch immer ein Bug in der Unit System.Net.HttpClient.Win, den man nur gelöst bekommt, indem man eine eigene Version der Unit in sein Projekt einbaut und die entscheidende Stelle patcht. Wer bessere Lösungen hat, gerne melden.

Ich versuche nochmal, das Problem, den Fehler und eine mögliche Lösung kurz zusammenzufassen (dann braucht ihr die bisherigen Beiträge nicht unbedingt lesen):

Problem:
Es soll ein Web Service innerhalb eines Unternehmsnetzwerks genutzt werden. Der Web Service wird auf einem Windows Server gehostet (konkret geht es hier um Web Services von Microsoft Dynamics NAV) und verlangt eine Authentifizierung, damit er genutzt werden kann. Da das ganze innerhalb eines Unternehmensnetzwerk passiert, kann eigentlich NTLM/Kerberos für die Authentifizierung genutzt und dabei die Credentials das aktuellen Benutzers genutzt werden. Heißt vereinfacht: Windows kümmert sich im Hntergrund um die Anmeldung am Web Service und der Benutzer muss seine Login-Daten nicht erneut eingeben bzw. man muss sie nicht selber irgendwo speichern. Bis Delphi 10.2.3 funktionierte das meist problemlos, ab Delphi 10.3.1 hat Emba die ganzen SOAP-Bibliotheken technisch komplett umgebaut, um sie auf THTTPClient umzubauen. Damit wird unter Windows nun nicht mehr die API WinInet, sondern WinHttp benutzt.

Der Fehler:
Wenn WinHttp mit NTLM arbeitet, dann gibt es eine Option, welche steuert, ob es mit den aktuellen Benutzer-Credentials arbeiten soll oder ob man Benutzername/Passwort angeben muss. Diese Option heißt WINHTTP_OPTION_AUTOLOGON_POLICY. Weist man ihr den Wert WINHTTP_AUTOLOGON_SECURITY_LEVEL_LOW zu, dann benutzt die Bibliothek den aktuellen Benutzer für den Login und Benutzername/Passwort werden erst gar nicht abgefragt. Weist man der Option hingegen den Wert WINHTTP_AUTOLOGON_SECURITY_LEVEL_HIGH zu, dann braucht man auf jeden Fall Benutzername/Passwort. In Rio 10.3.1 wurde das überhaupt nicht beachtet, somit war ein Login zum Web Service unter Benutzung des aktuellen Benutzers nicht möglich. In Rio 10.3.2 hat man versucht, das Problem anzugehen und die neue Eigenschaft "useDefaultCredentials" im THTTPClient und im WebNode eingeführt. Dann gibt es folgende Funktion:

Delphi-Quellcode:
procedure TWinHTTPRequest.SetWinLogonPolicy;
var
  LClient: TWinHTTPClient;
  LOption: DWORD;
begin
  LClient := TWinHTTPClient(FClient);
  if LClient.UseDefaultCredentials then
    LOption := WINHTTP_AUTOLOGON_SECURITY_LEVEL_LOW
  else
    LOption := WINHTTP_AUTOLOGON_SECURITY_LEVEL_HIGH;
  WinHttpSetOption(FWRequest, WINHTTP_OPTION_AUTOLOGON_POLICY, @LOption, SizeOf(LOption));
end;
Sieht eigentlich super aus, funktioniert aber nicht. Das Problem ist, dass die das "UseDefaultCredentials" nicht einfach im THTTPClient speichern, sondern in einem Record, der wiederum irgendwie in einem Dictionary steckt - da war ich dann irgendwann mit meinem Latein oder meiner Geduld am Ende und es mag sich gerne noch mal jemand ansehen. Der Effekt ist jedenfalls der: man weist zwar in seinem Code dem UseDefaultCredentials ein "true" zu, aber wenn dann die Verbindung tatsächlich initialisiert und somit die obige Funktion aufgerufen wird, dann ist es trotzdem immer noch "false". Die Folge: die Option WINHTTP_OPTION_AUTOLOGON_POLICY wird auf den falschen Wert gesetzt und WinHttp erwartet einen Aufruf von "SetCredentials" mit manuell mitgegebenem Benutzernamen und Passwort.

(hässlicher) Workaround:
Aktuell fällt mir nichts besseres ein, als eine eigene Version der Unit in mein Projekt zu kopieren und dort die Funktion wie folgt anzupassen:

Delphi-Quellcode:
procedure TWinHTTPRequest.SetWinLogonPolicy;
var
  LClient: TWinHTTPClient;
  LOption: DWORD;
begin
  LClient := TWinHTTPClient(FClient);
  if LClient.UseDefaultCredentials or forceSecurityLevelLow then
    LOption := WINHTTP_AUTOLOGON_SECURITY_LEVEL_LOW
  else
    LOption := WINHTTP_AUTOLOGON_SECURITY_LEVEL_HIGH;
  WriteDebugMessage('SetWinLogonPolicy: call WinHttpSetOption with Option '+IntToStr(LOption));
  WinHttpSetOption(FWRequest, WINHTTP_OPTION_AUTOLOGON_POLICY, @LOption, SizeOf(LOption));
end;
Der entscheidende Unterschied ist nur if LClient.UseDefaultCredentials or forceSecurityLevelLow then . Ich habe hier im interface-Teil noch eine globale Variable ergänzt und kann diese nun vom eigentlichen Programm aus auf true setzen, um das zu erreichen, was ja eigentlich "UseDefaultCredentials" selber tun sollte. Dann klappt ein Login am Server, ohne dass man Benutzername/Passwort irgendwo speichern und angeben muss.

Ich werde dann wohl mal einen Eintrag bei QC dazu machen...
  Mit Zitat antworten Zitat
TiGü

Registriert seit: 6. Apr 2011
Ort: Berlin
3.079 Beiträge
 
Delphi 10.4 Sydney
 
#3

AW: Probleme mit SOAP von 10.2.3 nach 10.3.1

  Alt 12. Sep 2019, 13:19
Sehr gut! Vielen Dank, dass du deine Erkenntnisse für die Nachwelt teilst.

Zusatzidee: Anstatt die ganze Unit zu kopieren, kannst du auch die Windows-Funktion WinHttpSetOption intercepten.
Siehe meine Beiträge hier: https://www.delphipraxis.net/198305-...-tls-win7.html
  Mit Zitat antworten Zitat
Bbommel

Registriert seit: 27. Jun 2007
Ort: Köln
672 Beiträge
 
Delphi 12 Athens
 
#4

AW: Probleme mit SOAP von 10.2.3 nach 10.3.1

  Alt 12. Sep 2019, 15:32
Danke für den Tipp. Das sieht dann in meiner Testanwendung so aus und funktioniert tatsächlich:
Delphi-Quellcode:
uses
  [...]
  DDetours, Winapi.WinHttp;
[...]

var
  TrampolinWinHttpSetOption: function(hInternet: HINTERNET; dwOption: DWORD;
                   lpBuffer: Pointer; dwBufferLength: DWORD): BOOL; stdcall=nil;

implementation

function InterceptWinHttpSetOption(hInternet: HINTERNET; dwOption: DWORD; lpBuffer: Pointer; dwBufferLength: DWORD): BOOL; stdcall;
var
  LOption: DWORD;
begin
  if dwOption=WINHTTP_OPTION_AUTOLOGON_POLICY then begin
    LOption := WINHTTP_AUTOLOGON_SECURITY_LEVEL_LOW;
    Result:=TrampolinWinHttpSetOption(hInternet, WINHTTP_OPTION_AUTOLOGON_POLICY, @LOption, SizeOf(LOption));
  end else
    Result:=TrampolinWinHttpSetOption(hInternet,dwOption,lpBuffer,dwBufferLength);
end;


{$R *.dfm}

[...]

procedure TmainSoapTest.FormCreate(Sender: TObject);

var
  strList: TStringList;

begin
  if not Assigned(TrampolinWinHttpSetOption) then
  begin
    @TrampolinWinHttpSetOption := InterceptCreate(@WinHttpSetOption, @InterceptWinHttpSetOption);
  end;
  [...]
end;
In einem echten Programm würde man vielleicht nicht ganz so rabiat vorgehen, sondern aus einer Programmkonfiguration abfragen, ob nicht vielleicht doch mit Benutzernamen/Passwort gearbeitet werden soll. Aber das Prinzip funktioniert. Jetzt muss ich mal in mich gehen, ob es mir lieber ist, eine zusätzliche externe Unit einzubinden (also DDetours) oder die ganze HTTClient.Win-Unit rabiat zu überschreiben. Hm. Ist ja hoffentlich nur bis zum nächsten Delphi-Update... Sinnvollere wäre wahrscheinlich wirklich die Sache mit dem Hook.

Hier noch das Ticket bei QC.
  Mit Zitat antworten Zitat
TurboMagic

Registriert seit: 28. Feb 2016
Ort: Nordost Baden-Württemberg
3.096 Beiträge
 
Delphi 12 Athens
 
#5

AW: Probleme mit SOAP von 10.2.3 nach 10.3.1

  Alt 12. Sep 2019, 18:37
Danke für das Erforschen und Publizieren der Lösung!

Nur die eine Frage bleibt noch offen: ist dieses Problem schon in QP erfasst,
damit es EMBT auch offiziell bekannt ist und hoffentlich in einer Folgeversion
behoben wird?
  Mit Zitat antworten Zitat
Bbommel

Registriert seit: 27. Jun 2007
Ort: Köln
672 Beiträge
 
Delphi 12 Athens
 
#6

AW: Probleme mit SOAP von 10.2.3 nach 10.3.1

  Alt 12. Sep 2019, 21:05
Nur die eine Frage bleibt noch offen: ist dieses Problem schon in QP erfasst, damit es EMBT auch offiziell bekannt ist und hoffentlich in einer Folgeversion behoben wird?
Jepp, steht am Ende meines letzten Posts, also direkt über deinem Beitrag. Ich hab zwar QC statt QP geschrieben, aber das sind doch bürgerliche Kategorien.

Hier nochmal der Link zum Eintrag im Quality Portal.
  Mit Zitat antworten Zitat
TurboMagic

Registriert seit: 28. Feb 2016
Ort: Nordost Baden-Württemberg
3.096 Beiträge
 
Delphi 12 Athens
 
#7

AW: Probleme mit SOAP von 10.2.3 nach 10.3.1

  Alt 13. Sep 2019, 17:29
Ja, genaues Lesen hätte mal wieder geholfen
Danke für's Erfassen des Problems!
  Mit Zitat antworten Zitat
Antwort Antwort


Forumregeln

Es 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

Gehe zu:

Impressum · AGB · Datenschutz · Nach oben
Alle Zeitangaben in WEZ +1. Es ist jetzt 16:05 Uhr.
Powered by vBulletin® Copyright ©2000 - 2025, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024-2025 by Thomas Breitkreuz