Durchführen eines Identitätswechsels für den Client

Das Beispiel für einen Identitätswechsel veranschaulicht, wie die Identität der Aufruferanwendung vom Dienst gewechselt wird, sodass der Dienst im Namen des Aufrufers auf Systemressourcen zugreifen kann.

Grundlage hierfür ist das Beispiel für selbst gehostete Dienste. Der Dienst und die Clientkonfigurationsdateien sind mit denen des Beispiels für selbst gehostete Dienste identisch.

Hinweis

Die Setupprozedur und die Buildanweisungen für dieses Beispiel befinden sich am Ende dieses Themas.

Im folgenden Codebeispiel wird gezeigt, dass der Servicecode so geändert wurde, dass die Add-Methode für den Dienst die Identität des Aufrufers mithilfe von OperationBehaviorAttribute annimmt.

[OperationBehavior(Impersonation = ImpersonationOption.Required)]
public double Add(double n1, double n2)
{
    double result = n1 + n2;
    Console.WriteLine("Received Add({0},{1})", n1, n2);
    Console.WriteLine("Return: {0}", result);
    DisplayIdentityInformation();
    return result;
}

Demzufolge wird der Sicherheitskontext des ausgeführten Threads so geändert, dass die Identität des Aufrufers angenommen wird, bevor die Add-Methode eingegeben und auf das Beenden der Methode zurückgesetzt wird.

Die im folgenden Codebeispiel veranschaulichte DisplayIdentityInformation-Methode ist eine Hilfsfunktion, mit der die Identität des Aufrufers dargestellt wird.

static void DisplayIdentityInformation()
{
    Console.WriteLine("\t\tThread Identity            :{0}",
         WindowsIdentity.GetCurrent().Name);
    Console.WriteLine("\t\tThread Identity level  :{0}",
         WindowsIdentity.GetCurrent().ImpersonationLevel);
    Console.WriteLine("\t\thToken                     :{0}",
         WindowsIdentity.GetCurrent().Token.ToString());
    return;
}

Im folgenden Codebeispiel wird gezeigt, dass die Subtract-Methode für den Dienst die Identität des Aufrufers mithilfe von imperativen Aufrufen annimmt.

public double Subtract(double n1, double n2)
{
    double result = n1 - n2;
    Console.WriteLine("Received Subtract({0},{1})", n1, n2);
    Console.WriteLine("Return: {0}", result);
    Console.WriteLine("Before impersonating");
    DisplayIdentityInformation();

    if (ServiceSecurityContext.Current.WindowsIdentity.ImpersonationLevel == TokenImpersonationLevel.Impersonation ||
        ServiceSecurityContext.Current.WindowsIdentity.ImpersonationLevel == TokenImpersonationLevel.Delegation)
    {
        // Impersonate.
        using (ServiceSecurityContext.Current.WindowsIdentity.Impersonate())
        {
            // Make a system call in the caller's context and ACLs
            // on the system resource are enforced in the caller's context.
            Console.WriteLine("Impersonating the caller imperatively");
            DisplayIdentityInformation();
        }
    }
    else
    {
        Console.WriteLine("ImpersonationLevel is not high enough to perform this operation.");
    }

    Console.WriteLine("After reverting");
    DisplayIdentityInformation();
    return result;
}

Beachten Sie, dass in diesem Fall kein Identitätswechsel für den gesamten Aufruf, sondern nur für einen Teil des Aufrufs vorgenommen wurde. Im Allgemeinen empfiehlt es sich, einen Identitätswechsel für den kleinsten Bereich und nicht für den ganzen Vorgang durchzuführen.

Die anderen Methoden nehmen die Identität des Aufrufers nicht an.

Der Clientcode wurde geändert, um die Identitätswechselebene auf Impersonation festzulegen. Der Client gibt die vom Dienst zu verwendende Identitätswechselebene durch die TokenImpersonationLevel-Enumeration an. Die Enumeration unterstützt die folgenden Werte: None, Anonymous, Identification, Impersonation und Delegation. Um beim Zugreifen auf die Systemressource auf dem lokalen Rechner, der mit Windows-Zugriffssteuerungslisten geschützt ist, eine Zugriffsprüfung durchzuführen, muss die Identitätswechselebene auf Impersonation festgelegt sein, wie im folgenden Codebeispiel gezeigt.

// Create a client with given client endpoint configuration
CalculatorClient client = new CalculatorClient();

client.ClientCredentials.Windows.AllowedImpersonationLevel = TokenImpersonationLevel.Impersonation;

Wenn Sie das Beispiel ausführen, werden die Anforderungen und Antworten für den Vorgang im Dienst- und Clientkonsolenfenster angezeigt. Drücken Sie die EINGABETASTE in den einzelnen Konsolenfenstern, um den Dienst und den Client zu schließen.

Hinweis

Der Dienst muss entweder auf einem Administratorkonto ausgeführt werden, oder das Konto, auf dem der Dienst ausgeführt wird, muss über Berechtigungen zum Registrieren des http://localhost:8000/ServiceModelSamples-URI mit der HTTP-Ebene verfügen. Solche Rechte können durch Einrichten einer Namespacereservierung mit dem Tool Httpcfg.exe gewährt werden.

Hinweis

Auf Computern unter Windows Server 2003 wird der Identitätswechsel nur unterstützt, wenn die Anwendung Host.exe über eine Berechtigung zum Identitätswechsel verfügt. Standardmäßig verfügen nur Administratoren über diese Berechtigung. Wechseln Sie zum Hinzufügen dieser Berechtigung zu einem Konto, auf dem der Dienst ausgeführt wird, navigieren Sie zu Verwaltungstools, öffnen Sie Lokale Sicherheitsrichtlinie, dann Lokale Richtlinien, und klicken Sie auf Zuweisen von Benutzerrechten. Wählen Sie dann die Option Wechseln der Clientidentität nach Authentifizierung aus, und doppelklicken Sie auf Eigenschaften, um einen oder eine Benutzer*in oder eine Gruppe hinzuzufügen.

So können Sie das Beispiel einrichten, erstellen und ausführen

  1. Stellen Sie sicher, dass Sie die Beispiele zum einmaligen Setupverfahren für Windows Communication Foundation ausgeführt haben.

  2. Um die C#- oder Visual Basic .NET-Edition der Projektmappe zu erstellen, befolgen Sie die unter Building the Windows Communication Foundation Samplesaufgeführten Anweisungen.

  3. Wenn Sie das Beispiel in einer Konfiguration mit einem Computer oder über Computer hinweg ausführen möchten, folgen Sie den Anweisungen unter Durchführen der Windows Communication Foundation-Beispiele.

  4. Wenn Sie veranschaulichen möchten, dass der Dienst die Identität des Aufrufers annimmt, führen Sie den Client auf einem anderen Konto als dem Konto aus, auf dem der Dienst ausgeführt wird. Geben Sie dazu an der Eingabeaufforderung Folgendes ein:

    runas /user:<machine-name>\<user-name> client.exe
    

    Sie werden anschließend zur Eingabe eines Kennworts aufgefordert. Geben Sie das Kennwort für das Konto ein, das Sie vorher angegeben haben.

  5. Wenn Sie den Client ausführen, beachten Sie die Identität vor und nach dem Ausführen mit unterschiedlichen Anmeldeinformationen.