it-swarm.com.de

Authentifizierung beim ASP.NET Web Api-Dienst mit HttpClient nicht möglich

Ich habe einen ASP.NET-Web-API-Dienst, der auf einem Webserver mit aktivierter Windows-Authentifizierung ausgeführt wird. 

Ich habe eine auf MVC4 erstellte Client-Site, die an einem anderen Standort auf demselben Webserver ausgeführt wird, der den HttpClient zum Abrufen von Daten aus dem Dienst verwendet. Diese Client-Site wird mit aktiviertem Identitätsidentitätswechsel ausgeführt und verwendet auch die Windows-Authentifizierung.

Der Webserver ist Windows Server 2008 R2 mit IIS 7.5.

Die Herausforderung, die ich habe, besteht darin, den HttpClient dazu zu bringen, den aktuellen Windows-Benutzer als Teil seines Authentifizierungsprozesses zu übergeben. Ich habe den HttpClient auf folgende Weise konfiguriert:

var clientHandler = new HttpClientHandler();
clientHandler.UseDefaultCredentials = true;
clientHandler.PreAuthenticate = true;
clientHandler.ClientCertificateOptions = ClientCertificateOption.Automatic;
var httpClient = new HttpClient(clientHandler);

Meines Wissens ist es so, dass das Ausführen der Site mit aktivierter Identitätsidentifizierung und das anschließende Erstellen des Clients auf diese Weise dazu führen, dass sich der Client bei dem Dienst mit der identifizierten Identität des aktuell angemeldeten Benutzers authentifiziert.

Das passiert nicht. Tatsächlich scheint sich der Client überhaupt nicht zu authentifizieren.

Der Dienst ist für die Verwendung der Windows-Authentifizierung konfiguriert. Dies scheint einwandfrei zu funktionieren. Ich kann in meinem Webbrowser nach http: // server/api/shippers gehen und zur Windows-Authentifizierung aufgefordert werden. Nach der Eingabe erhalte ich die angeforderten Daten.

In den IIS -Protokollen sehe ich, dass die API-Anforderungen ohne Authentifizierung empfangen werden und eine 401-Antwortantwort erhalten.

Die Dokumentation dazu scheint spärlich zu sein. 

Ich brauche etwas Einblick in was falsch sein könnte oder eine andere Möglichkeit, die Windows-Authentifizierung mit dieser Anwendung zu verwenden. 

Vielen Dank, Craig

35
Craig Anderson

Ich habe den Quellcode von HttpClientHandler (der neuesten Version, die ich in die Finger bekommen konnte) untersucht. Dies ist das, was in der SendAsync-Methode gefunden werden kann:

// BeginGetResponse/BeginGetRequestStream have a lot of setup work to do before becoming async
// (proxy, dns, connection pooling, etc).  Run these on a separate thread.
// Do not provide a cancellation token; if this helper task could be canceled before starting then 
// nobody would complete the tcs.
Task.Factory.StartNew(startRequest, state);

Wenn Sie nun den Wert von SecurityContext.IsWindowsIdentityFlowSuppressed () in Ihrem Code überprüfen, werden Sie höchstwahrscheinlich "true" erhalten. Als Ergebnis wird die StartRequest-Methode in einem neuen Thread mit den Berechtigungsnachweisen des asp.net-Prozesses (nicht den Berechtigungsnachweisen des imitierten Benutzers) ausgeführt.

Hier gibt es zwei Möglichkeiten. Wenn Sie Zugriff auf Ihren Server aspnet_config.config haben, sollten Sie die folgenden Einstellungen festlegen (die Einstellung in web.config scheint keine Auswirkung zu haben):

<legacyImpersonationPolicy enabled="false"/>
<alwaysFlowImpersonationPolicy enabled="true"/>

Wenn Sie die aspnet_config.config nicht ändern können, müssen Sie Ihren eigenen HttpClientHandler erstellen, um dieses Szenario zu unterstützen.

AKTUALISIERUNG ÜBER DEN GEBRAUCH VON FQDN

Das Problem, das Sie hier gefunden haben, ist eine Funktion in Windows, die vor "Reflexionsangriffen" schützen soll. Um dies zu umgehen, müssen Sie die Domäne, auf die Sie zugreifen möchten, auf der Maschine, die versucht, auf den Server zuzugreifen, auf die Whitelist setzen. Befolgen Sie die folgenden Schritte:

  1. Gehen Sie zu Start -> Ausführen -> regedit
  2. Suchen Sie den HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\Lsa\MSV1_0-Registrierungsschlüssel.
  3. Klicken Sie mit der rechten Maustaste darauf, wählen Sie Neu und dann Multi-String-Wert.
  4. Geben Sie BackConnectionHostNames (_ geben Sie _ ein) ein.
  5. Klicken Sie mit der rechten Maustaste auf den gerade erstellten Wert und wählen Sie Ändern.
  6. Geben Sie die Hostnamen für die Sites, die sich auf dem lokalen Computer befinden, in das Wertefeld ein und klicken Sie auf OK (Jeder Hostname/FQDN muss sich in seiner eigenen Zeile befinden, keine Platzhalterzeichen) , muss der Name genau übereinstimmen).
  7. Speichern Sie alles und starten Sie die Maschine neu

Sie können den gesamten KB-Artikel zum Thema hier lesen.

32
tpeczek

Ich hatte auch das gleiche Problem. Dank der von @tpeczek durchgeführten Recherche entwickelte ich die folgende Lösung: Anstelle des HttpClient (der Threads erstellt und Anforderungen async sendet), habe ich die WebClient-Klasse verwendet, die Anforderungen für denselben Thread ausgibt. Dadurch kann ich die Identität des Benutzers von einer anderen ASP.NET-Anwendung an WebAPI weitergeben. 

Der offensichtliche Nachteil ist, dass dies nicht asynchron funktioniert.

var wi = (WindowsIdentity)HttpContext.User.Identity;

var wic = wi.Impersonate();
try
{
    var data = JsonConvert.SerializeObject(new
    {
        Property1 = 1,
        Property2 = "blah"
    });

    using (var client = new WebClient { UseDefaultCredentials = true })
    {
        client.Headers.Add(HttpRequestHeader.ContentType, "application/json; charset=utf-8");
        client.UploadData("http://url/api/controller", "POST", Encoding.UTF8.GetBytes(data));
    }
}
catch (Exception exc)
{
    // handle exception
}
finally
{
    wic.Undo();
}

Hinweis: Erfordert das NuGet-Paket: Newtonsoft.Json, dasselbe JSON-Serialisierungsprogramm, das auch WebAPI verwendet.

9
Joshua

Der Grund, warum dies nicht funktioniert, liegt darin, dass Sie die Double-Hop-Authentifizierung benötigen.

Der erste Hop ist der Webserver. Um Identitätswechsel mit der Windows-Authentifizierung zu gewährleisten, gibt es kein Problem. Wenn Sie jedoch HttpClient oder WebClient verwenden, um sich bei einem anderen Server zu authentifizieren, muss der Webserver unter einem Konto ausgeführt werden, das über die Berechtigung zum Ausführen der erforderlichen Delegierung verfügt.

Weitere Einzelheiten finden Sie im Folgenden:
http://blogs.technet.com/b/askds/archive/2008/06/13/understanding-kerberos-double-hop.aspx

Fix mit dem Befehl "setspn":
http://www.phishthis.com/2009/10/24/how-to-configure-ad-sql-und-iis-for-two-hop-kerberos-authentication-2/ (Sie benötigen ausreichende Zugriffsrechte, um diese Vorgänge auszuführen.)

Überlegen Sie nur, was passieren würde, wenn ein Server Ihre Anmeldeinformationen nach Belieben weiterleiten könnte ... Um dieses Sicherheitsproblem zu vermeiden, muss der Domänencontroller wissen, welche Konten die Delegierung durchführen dürfen.

0
Luis Cantero

Verwenden Sie zum Identifizieren des ursprünglichen (authentifizierten) Benutzers die folgende Konfiguration in der Datei Web.config:

<authentication mode="Windows" />
<identity impersonate="true" />

Bei dieser Konfiguration nimmt ASP.NET immer den authentifizierten Benutzer an, und der gesamte Ressourcenzugriff wird mit dem Sicherheitskontext des authentifizierten Benutzers ausgeführt.

0
Hardik Patel