wake-up-neo.net

HttpClient & Windows Auth: Den angemeldeten Benutzer des Verbrauchers an den Dienst übergeben

Ich habe Schwierigkeiten, einen Service und einen Consumer zu verstehen und einzurichten, wobei der Service ausgeführt wird, wenn der Benutzer beim Consumer angemeldet ist.

Mein Verbraucher ist eine MVC-Anwendung. Mein Service ist eine Web-API-Anwendung. Beide laufen auf separaten Servern in derselben Domäne. Beide sind auf Windows Auth eingestellt.

Mein Verbraucherkode lautet:

private T GenericGet<T>(string p)
    {
        T result = default(T);

        HttpClientHandler handler = new HttpClientHandler() { PreAuthenticate = true, UseDefaultCredentials = true };
        using (HttpClient client = new HttpClient(handler))
        {
            client.BaseAddress = new Uri(serviceEndPoint);

            HttpResponseMessage response = client.GetAsync(p).Result;
            if (response.IsSuccessStatusCode)
                result = response.Content.ReadAsAsync<T>().Result;
        }

        return result;
    }

In meinem Dienst rufe ich User.Identity.Name an, um die Anrufer-ID zu erhalten, diese wird jedoch immer als Verbraucher-App-Pool-ID und nicht als angemeldeter Benutzer zurückgegeben. Der Consumer-App-Pool wird als Netzwerkdienst ausgeführt. Der Server selbst wird für die Delegierung als vertrauenswürdig eingestuft. Wie bekomme ich den angemeldeten Benutzer? Service code:

    // GET: /Modules/5/Permissions/
    [Authorize]
    public ModulePermissionsDTO Get(int ModuleID)
    {
        Module module= moduleRepository.Find(ModuleID);
        if (module== null)
            throw new HttpResponseException(HttpStatusCode.NotFound);

        // This just shows as the App Pool the MVC consumer is running as (Network Service).
        IPrincipal loggedInUser = User;

        // Do I need to do something with this instead?
        string authHeader = HttpContext.Current.Request.Headers["Authorization"];

        ModulePermissionsDTO dto = new ModulePermissionsDTO();
        // Construct object here based on User...

        return dto;
    }

Gemäß dieser Frage ist Kerberos erforderlich, damit diese Einrichtung funktioniert, da der HttpClient in einem separaten Thread ausgeführt wird. Dies verwirrt mich jedoch, weil ich der Meinung war, dass die Anforderung einen Autorisierungsheader sendet, und dass der Dienst dies in der Lage sein sollte, das Benutzertoken abzurufen. Wie auch immer, ich habe einige Tests mit Kerberos durchgeführt, um zu überprüfen, ob dies in meiner Domäne ordnungsgemäß funktioniert, indem die Demo in "Situation 5" hier verwendet wird. Dies funktioniert jedoch, aber meine beiden Anwendungen geben den angemeldeten Benutzer nicht korrekt weiter.

Was muss ich tun, damit das funktioniert? Ist Kerberos erforderlich oder muss ich etwas in meinem Dienst tun, um den Autorisierungsheader zu entpacken und ein Hauptobjekt aus dem Token zu erstellen? Alle Ratschläge werden geschätzt.

14
James

Der Schlüssel besteht darin, dass Ihre MVC-Anwendung (Verbraucher) den aufrufenden Benutzer annimmt und dann die HTTP-Anforderungen synchron ausgibt (d. H. Ohne einen neuen Thread zu erzeugen). Sie sollten sich nicht mit Low-Level-Implementierungsdetails wie NTLM vs. Kerberos beschäftigen müssen.

Verbraucher

Konfigurieren Sie Ihre MVC-Anwendung wie folgt: 

  1. Starten Sie IIS Manager
  2. Wählen Sie Ihre MVC-Webanwendung aus
  3. Doppelklicken Sie auf "Authentifizierung".
  4. Aktivieren Sie 'ASP.NET-Identitätswechsel'
  5. Aktivieren 'Windows-Authentifizierung'
  6. Deaktivieren Sie andere Formen der Authentifizierung (außer vielleicht Digest, wenn Sie es brauchen)
  7. Öffnen Sie die Datei Web.config im Stammverzeichnis Ihrer MVC-Anwendung, und stellen Sie sicher, dass <authentication mode="Windows" />

Um die HTTP-Anfrage auszustellen, empfehle ich, die ausgezeichnete RestSharp library zu verwenden. Beispiel:

var client = new RestClient("<your base url here>");
client.Authenticator = new NtlmAuthenticator();
var request = new RestRequest("Modules/5/Permissions", Method.GET);
var response = client.Execute<ModulePermissionsDTO>(request);

Bedienung

Konfigurieren Sie Ihren Web-API-Dienst wie folgt: 

  1. Starten Sie IIS Manager
  2. Wählen Sie Ihren Web-API-Dienst aus
  3. Doppelklicken Sie auf "Authentifizierung".
  4. Deaktivieren 'ASP.NET-Identitätswechsel'.
  5. Aktivieren 'Windows-Authentifizierung'
  6. Wenn nur für eine Teilmenge Ihrer Web-API-Methoden Benutzer authentifiziert werden müssen, lassen Sie "Anonyme Authentifizierung" aktiviert. 
  7. Öffnen Sie die Datei "Web.config" im Stammverzeichnis Ihres Web-API-Diensts und stellen Sie sicher, dass <authentication mode="Windows" />

Ich kann sehen, dass Sie Ihre Methode bereits mit einem [Authorize]-Attribut versehen haben, das eine Authentifizierungsaufforderung (HTTP 401) auslösen soll, wenn auf die Methode zugegriffen wird. Jetzt sollten Sie über die User.Identity-Eigenschaft Ihrer ApiController-Klasse auf die Identität Ihres Endbenutzers zugreifen können.

Das Hauptproblem bei Double Hop ist die Delegierung der Benutzeranmeldeinformationen an den zweiten Anruf. Ich möchte etwas näher darauf eingehen. C1 = Clientbrowser, S1 = Erster Server, S2 = Zweiter Server. 

Angenommen, unsere vollständige System-Support-Fensterauthentifizierung. Wenn der Benutzer vom Browser aus auf S1 zugreift, wird der Standard-Anmeldeinformationsbereich des Fensters an den Server S1 übergeben. Wenn S1 jedoch einen Aufruf an S2 durchführt, übergibt er standardmäßig keine Anmeldeinformationen an S2.

Auflösung : 

  1. Wir müssen die Fensterauthentifizierung/Identitätswechsel auf beiden Computern aktivieren.
  2. Wir müssen die Delegierung zwischen Servern aktivieren, damit S1 auf S2 vertrauen kann und die Berechtigung an S2 weitergibt.

Einige nützliche Informationen finden Sie unter den folgenden Links: Http://blogs.msdn.com/b/farukcelik/archive/2008/01/02/how-to-set-up-a-kerberos-authentication -scenario-with-sql-server-linked-servers.aspx

https://sqlbadboy.wordpress.com/2013/10/11/the-kerberos-double-hop-problem/

0
Rahul Garg

Wenn Sie versuchen, auf einen Dienst zuzugreifen, der von der Windows-Authentifizierung gehostet wird, führen Sie die folgenden Schritte aus.

var request = new RestRequest(Method.POST);

Wenn Sie Standardanmeldeinformationen für Anwendungen verwenden möchten, die Zugriff auf den gehosteten Service-Server haben müssen

request.UseDefaultCredentials = true;

oder Benutzer unten, um die Anmeldeinformationen manuell zu übergeben

request.Credentials = new NetworkCredential("Username", "Password", "Domain");
0