Ich habe eine Webanwendung (in IIS gehostet), die mit einem Windows-Dienst kommuniziert. Der Windows-Dienst verwendet die ASP.Net MVC-Web-API (selbst gehostet) und kann daher über JSON über http kommuniziert werden. Die Webanwendung ist für den Identitätswechsel konfiguriert. Die Idee besteht darin, dass der Benutzer, der die Anforderung an die Webanwendung stellt, der Benutzer sein sollte, mit dem die Webanwendung die Anforderung an den Dienst sendet. Die Struktur sieht folgendermaßen aus:
(Der rot hervorgehobene Benutzer ist der Benutzer, auf den in den folgenden Beispielen verwiesen wird.)
Die Webanwendung sendet Anforderungen an den Windows-Dienst mit HttpClient
:
var httpClient = new HttpClient(new HttpClientHandler()
{
UseDefaultCredentials = true
});
httpClient.GetStringAsync("http://localhost/some/endpoint/");
Dadurch wird die Anforderung an den Windows-Dienst gesendet, die Anmeldeinformationen werden jedoch nicht korrekt übergeben (der Dienst meldet den Benutzer als IIS APPPOOL\ASP.NET 4.0
). Das will ich nicht .
Wenn ich den obigen Code so ändere, dass WebClient
stattdessen a verwendet wird, werden die Anmeldeinformationen des Benutzers korrekt übergeben:
WebClient c = new WebClient
{
UseDefaultCredentials = true
};
c.DownloadStringAsync(new Uri("http://localhost/some/endpoint/"));
Mit dem obigen Code meldet der Dienst den Benutzer als den Benutzer, der die Anforderung an die Webanwendung gestellt hat.
Was mache ich falsch mit der HttpClient
Implementierung, die dazu führt, dass die Anmeldeinformationen nicht korrekt übergeben werden (oder liegt ein Fehler mit der vor HttpClient
)?
Der Grund, warum ich das verwenden möchte, HttpClient
ist, dass es eine asynchrone API hat, die gut mit Task
s funktioniert , während die WebClient
asyc-API der mit Ereignissen behandelt werden muss.
quelle
DownloadStringTaskAsync
in .Net 4.5, das auch mit async / await verwendet werden kannHttpClient
hat keineSetCredentials()
Methode. Können Sie mich auf das hinweisen, was Sie meinen?new HttpClient(new HttpClientHandler() { AllowAutoRedirect = true, UseDefaultCredentials = true }
auf einem Webserver zu erstellen, auf den ein Windows-authentifizierter Benutzer zugreift, und die Website hat sich danach für eine andere Remote-Ressource authentifiziert (würde sich ohne gesetztes Flag nicht authentifizieren).Antworten:
Ich hatte auch das gleiche Problem. Ich habe dank der von @tpeczek im folgenden SO-Artikel durchgeführten Recherche eine synchrone Lösung entwickelt: Authentifizierung beim ASP.NET Web Api-Dienst mit HttpClient nicht möglich
Meine Lösung verwendet eine
WebClient
, die, wie Sie richtig notiert haben, die Anmeldeinformationen ohne Probleme weitergibt. Der Grund, warumHttpClient
dies nicht funktioniert, liegt darin, dass die Windows-Sicherheit die Möglichkeit deaktiviert, neue Threads unter einem imitierten Konto zu erstellen (siehe SO-Artikel oben).HttpClient
Über die Task Factory werden neue Threads erstellt, wodurch der Fehler verursacht wird.WebClient
Auf der anderen Seite wird synchron auf demselben Thread ausgeführt, wodurch die Regel umgangen und ihre Anmeldeinformationen weitergeleitet werden.Obwohl der Code funktioniert, ist der Nachteil, dass er nicht asynchron funktioniert.
Hinweis: Erfordert das NuGet-Paket: Newtonsoft.Json, das der gleiche JSON-Serializer ist, den WebAPI verwendet.
quelle
Sie können so konfigurieren
HttpClient
, dass Anmeldeinformationen wie folgt automatisch übergeben werden:quelle
Sie versuchen, NTLM dazu zu bringen, die Identität an den nächsten Server weiterzuleiten, was nicht möglich ist. Es kann nur einen Identitätswechsel durchführen, bei dem Sie nur auf lokale Ressourcen zugreifen können. Sie können keine Maschinengrenze überschreiten. Die Kerberos-Authentifizierung unterstützt die Delegierung (was Sie benötigen) mithilfe von Tickets. Das Ticket kann weitergeleitet werden, wenn alle Server und Anwendungen in der Kette korrekt konfiguriert sind und Kerberos in der Domäne korrekt eingerichtet ist. Kurz gesagt, Sie müssen von NTLM zu Kerberos wechseln.
Weitere Informationen zu den Windows-Authentifizierungsoptionen und deren Funktionsweise finden Sie unter: http://msdn.microsoft.com/en-us/library/ff647076.aspx
quelle
WebClient
? Das ist das , was ich nicht verstehe - wenn es nicht möglich ist, wie kommt es ist , es zu tun?WebClient
die NTLM-Anmeldeinformationen weitergeben kann, dasHttpClient
aber nicht. Ich kann dies nur mit dem ASP.Net-Identitätswechsel erreichen, ohne Kerberos verwenden oder Benutzernamen / Kennwörter speichern zu müssen. Dies funktioniert jedoch nur mitWebClient
.OK, also danke an alle oben genannten Mitwirkenden. Ich verwende .NET 4.6 und wir hatten auch das gleiche Problem. Ich verbrachte Zeit mit dem Debuggen
System.Net.Http
, insbesondere demHttpClientHandler
, und fand Folgendes:Nachdem
ExecutionContext.IsFlowSuppressed()
ich festgestellt hatte , dass dies möglicherweise der Schuldige war, habe ich unseren Identitätswechselcode wie folgt verpackt:Der Code in
SafeCaptureIdenity
(nicht mein Rechtschreibfehler) greiftWindowsIdentity.Current()
nach unserer Identität. Dies wird aufgegriffen, weil wir jetzt den Fluss unterdrücken. Aufgrund der Verwendung / Entsorgung wird diese nach dem Aufruf zurückgesetzt.Es scheint jetzt für uns zu funktionieren, Puh!
quelle
using (System.Threading.ExecutionContext.SuppressFlow())
und das Problem wurde für mich gelöst!In .NET Kern konnte ich eine bekommen
System.Net.Http.HttpClient
mitUseDefaultCredentials = true
dem authentifizierten Benutzer-Windows - Anmeldeinformationen an einen Back - End - Dienst durchlaufen , indem SieWindowsIdentity.RunImpersonated
.quelle
Es hat bei mir funktioniert, nachdem ich einen Benutzer mit Internetzugang im Windows-Dienst eingerichtet habe.
In meinem Code:
quelle
Ok, also habe ich Joshoun-Code genommen und ihn generisch gemacht. Ich bin nicht sicher, ob ich ein Singleton-Muster für die SynchronousPost-Klasse implementieren soll. Vielleicht kann jemand mit mehr Wissen helfen.
Implementierung
// Ich nehme an, Sie haben Ihren eigenen konkreten Typ. In meinem Fall verwende ich zuerst Code mit einer Klasse namens FileCategoryGenerische Klasse hier. Sie können jeden Typ übergeben
Meine Api-Klassen sehen so aus, wenn Sie neugierig sind
Ich benutze Ninject und Repo-Muster mit Arbeitseinheit. Wie auch immer, die obige generische Klasse hilft wirklich.
quelle