Vorgehensweise: Erstellen einer benutzerdefinierten ClientidentitätsüberprüfungHow to: Create a Custom Client Identity Verifier

Die Identität Feature von Windows Communication Foundation (WCF) kann ein Client im Voraus angeben der erwarteten Identität des Diensts.The identity feature of Windows Communication Foundation (WCF) enables a client to specify in advance the expected identity of the service. Bei jeder Authentifizierung eines Servers beim Client wird die Identität mit der erwarteten Identität verglichen.Whenever a server authenticates itself to the client, the identity is checked against the expected identity. (Eine Erläuterung der Identitäts- und deren Funktionsweise, finden Sie unter -Dienstidentität und Authentifizierung.)(For an explanation of identity and how it works, see Service Identity and Authentication.)

Sofern erforderlich, kann die Überprüfung mit einer benutzerdefinierten Identitätsüberprüfung angepasst werden.If needed, the verification can be customized using a custom identity verifier. Zum Beispiel können Sie zusätzliche Dienstidentitätsüberprüfungen durchführen.For example, you can perform additional service identity verification checks. In diesem Beispiel überprüft die benutzerdefinierte Identitätsprüfung zusätzliche Ansprüche in dem X.509-Zertifikat, das vom Server zurückgegeben wird.In this example, the custom identity verifier checks additional claims in the X.509 certificate returned from the server. Eine beispielanwendung finden Sie unter Dienstidentitätsbeispiel.For a sample application, see Service Identity Sample.

So erweitern Sie die EndpointIdentity-Klasse:To extend the EndpointIdentity class

  1. Definieren Sie eine neue Klasse, die von der EndpointIdentity-Klasse abgeleitet wird.Define a new class that derives from the EndpointIdentity class. In diesem Beispiel wird die Erweiterung OrgEndpointIdentity genannt.This example names the extension OrgEndpointIdentity.

  2. Fügen Sie private Member mit Eigenschaften hinzu, die von der erweiterten IdentityVerifier-Klasse zum Ausführen der Identitätsprüfung anhand der Ansprüche im vom Dienst zurückgegebenen Sicherheitstoken verwendet wird.Add private members along with properties that will be used by the extended IdentityVerifier class to perform the identity check against claims in the security token returned from the service. Dieses Beispiel definiert eine Eigenschaft: die OrganizationClaim-Eigenschaft.This example defines one property: the OrganizationClaim property.

    public class OrgEndpointIdentity : EndpointIdentity
    {
        private string orgClaim;
        public OrgEndpointIdentity(string orgName)
        {
            orgClaim = orgName;
        }
    
        public string OrganizationClaim
        {
            get { return orgClaim; }
            set { orgClaim = value; }
        }
    }
    
    Public Class OrgEndpointIdentity
        Inherits EndpointIdentity
        Private orgClaim As String
    
        Public Sub New(ByVal orgName As String)
            orgClaim = orgName
        End Sub
    
        Public Property OrganizationClaim() As String
            Get
                Return orgClaim
            End Get
            Set(ByVal value As String)
                orgClaim = value
            End Set
        End Property
    End Class
    

So erweitern Sie die IdentityVerifier-Klasse:To extend the IdentityVerifier class

  1. Definieren Sie eine neue Klasse, die von IdentityVerifier abgeleitet wird.Define a new class that derives from IdentityVerifier. In diesem Beispiel wird die Erweiterung CustomIdentityVerifier genannt.This example names the extension CustomIdentityVerifier.

    public class CustomIdentityVerifier : IdentityVerifier
    {
        // Code to be added.
        public override bool CheckAccess(EndpointIdentity identity, AuthorizationContext authContext)
        {
            throw new Exception("The method or operation is not implemented.");
        }
    
        public override bool TryGetIdentity(EndpointAddress reference, out EndpointIdentity identity)
        {
            throw new Exception("The method or operation is not implemented.");
        }
    }
    
    Public Class CustomIdentityVerifier
        Inherits IdentityVerifier
        ' Code to be added.
    
        Public Overrides Function CheckAccess(ByVal identity As EndpointIdentity, _
                                              ByVal authContext As AuthorizationContext) As Boolean
            Throw New Exception("The method or operation is not implemented.")
        End Function
    
        Public Overrides Function TryGetIdentity(ByVal reference As EndpointAddress, _
                                                 <System.Runtime.InteropServices.Out()> ByRef identity As EndpointIdentity) As Boolean
            Throw New Exception("The method or operation is not implemented.")
        End Function
    End Class
    
  2. Überschreiben Sie die CheckAccess-Methode.Override the CheckAccess method. Mit dieser Methode wird bestimmt, ob die Identitätsprüfung erfolgreich war oder fehlgeschlagen ist.The method determines whether the identity check succeeded or failed.

  3. Die CheckAccess-Methode verfügt über zwei Parameter.The CheckAccess method has two parameters. Der erste Parameter ist eine Instanz der EndpointIdentity-Klasse.The first is an instance of the EndpointIdentity class. Der zweite Parameter ist eine Instanz der AuthorizationContext-Klasse.The second is an instance of the AuthorizationContext class.

    Prüfen Sie in der Methodenimplementierung die Auflistung der von der ClaimSets-Eigenschaft der AuthorizationContext-Klasse zurückgegebenen Ansprüche, und führen Sie gemäß Bedarf Authentifizierungsprüfungen aus.In the method implementation, examine the collection of claims returned by the ClaimSets property of the AuthorizationContext class, and perform authentication checks as required. Dieses Beispiel beginnt durch Suchen eines Anspruchs vom Typ "Distinguished Name" und anschließendes Vergleichen des Namens mit der Erweiterung von EndpointIdentity (OrgEndpointIdentity).This example begins by finding any claim that is of type "Distinguished Name" and then compares the name to the extension of the EndpointIdentity (OrgEndpointIdentity).

    public override bool CheckAccess(EndpointIdentity identity, AuthorizationContext authContext)
    {
        bool returnvalue = false;
    
        foreach (ClaimSet claimset in authContext.ClaimSets)
        {
            foreach (Claim claim in claimset)
            {
                if (claim.ClaimType == "http://schemas.microsoft.com/ws/2005/05/identity/claims/x500distinguishedname")
                {
                    X500DistinguishedName name = (X500DistinguishedName)claim.Resource;
                    if (name.Name.Contains(((OrgEndpointIdentity)identity).OrganizationClaim))
                    {
                        Console.WriteLine("Claim Type: {0}", claim.ClaimType);
                        Console.WriteLine("Right: {0}", claim.Right);
                        Console.WriteLine("Resource: {0}", claim.Resource);
                        Console.WriteLine();
                        returnvalue = true;
                    }
                }
            }
    
        }
        return returnvalue;
    }
    
    
    Public Overrides Function CheckAccess(ByVal identity As EndpointIdentity, _
                                          ByVal authContext As AuthorizationContext) As Boolean
    
        Dim returnvalue = False
        For Each claimset In authContext.ClaimSets
            For Each claim In claimset
                If claim.ClaimType = "http://schemas.microsoft.com/ws/2005/05/identity/claims/x500distinguishedname" Then
                    Dim name = CType(claim.Resource, X500DistinguishedName)
                    If name.Name.Contains((CType(identity, OrgEndpointIdentity)).OrganizationClaim) Then
                        Console.WriteLine("Claim Type: {0}", claim.ClaimType)
                        Console.WriteLine("Right: {0}", claim.Right)
                        Console.WriteLine("Resource: {0}", claim.Resource)
                        Console.WriteLine()
                        returnvalue = True
                    End If
                End If
            Next claim
        Next claimset
        Return returnvalue
    
    End Function
    

So implementieren Sie die TryGetIdentity-Methode:To implement the TryGetIdentity method

  1. Implementieren Sie die TryGetIdentity-Methode, mit der bestimmt wird, ob vom Client eine Instanz der EndpointIdentity-Klasse zurückgegeben werden kann.Implement the TryGetIdentity method, which determines whether an instance of the EndpointIdentity class can be returned by the client. Ruft die WCF-Infrastruktur die Implementierung der TryGetIdentity Methode zuerst an, um die Identität des Diensts aus der Nachricht abzurufen.The WCF infrastructure calls the implementation of the TryGetIdentity method first to retrieve the service's identity from the message. Anschließend ruft die Infrastruktur die CheckAccess-Implementierung mit der zurückgegebenen EndpointIdentity und dem zurückgegebenen AuthorizationContext auf.Next, the infrastructure calls the CheckAccess implementation with the returned EndpointIdentity and AuthorizationContext.

  2. Fügen Sie in die TryGetIdentity-Methode folgenden Code ein:In the TryGetIdentity method, put the following code:

    public override bool TryGetIdentity(EndpointAddress reference, out EndpointIdentity identity)
    {
        return IdentityVerifier.CreateDefault().TryGetIdentity(reference, out identity);
    }
    
    Public Overrides Function TryGetIdentity(ByVal reference As EndpointAddress, _
                                             <System.Runtime.InteropServices.Out()> ByRef identity As EndpointIdentity) As Boolean
        Return IdentityVerifier.CreateDefault().TryGetIdentity(reference, identity)
    End Function
    
    

So implementieren Sie eine benutzerdefinierte Bindung und legen den benutzerdefinierten IdentityVerifier fest:To implement a custom binding and set the custom IdentityVerifier

  1. Erstellen Sie eine Methode, von der ein Binding-Objekt zurückgegeben wird.Create a method that returns a Binding object. In diesem Beispiel wird zunächst eine Instanz der WSHttpBinding-Klasse erstellt und der Sicherheitsmodus auf Message und der ClientCredentialType auf None festgelegt.This example begins creates an instance of the WSHttpBinding class and sets its security mode to Message, and its ClientCredentialType to None.

  2. Erstellen Sie mit der BindingElementCollection-Methode CreateBindingElements.Create a BindingElementCollection using the CreateBindingElements method.

  3. Geben Sie SecurityBindingElement aus der Auflistung zurück, und wandeln Sie sie in eine SymmetricSecurityBindingElement-Variable um.Return the SecurityBindingElement from the collection and cast it to a SymmetricSecurityBindingElement variable.

  4. Legen Sie die IdentityVerifier-Eigenschaft der LocalClientSecuritySettings-Klasse auf eine neue Instanz der zuvor erstellten CustomIdentityVerifier-Klasse fest.Set the IdentityVerifier property of the LocalClientSecuritySettings class to a new instance of the CustomIdentityVerifier class created previously.

    public static Binding CreateCustomSecurityBinding()
    {
        WSHttpBinding binding = new WSHttpBinding(SecurityMode.Message);
        //Clients are anonymous to the service.
        binding.Security.Message.ClientCredentialType = MessageCredentialType.None;
        //Secure conversation is turned off for simplification. If secure conversation is turned on, then 
        //you also need to set the IdentityVerifier on the secureconversation bootstrap binding.
        binding.Security.Message.EstablishSecurityContext = false;
    
        // Get the SecurityBindingElement and cast to a SymmetricSecurityBindingElement to set the IdentityVerifier.
        BindingElementCollection outputBec = binding.CreateBindingElements();
        SymmetricSecurityBindingElement ssbe = (SymmetricSecurityBindingElement)outputBec.Find<SecurityBindingElement>();
    
        //Set the Custom IdentityVerifier.
        ssbe.LocalClientSettings.IdentityVerifier = new CustomIdentityVerifier();
    
        return new CustomBinding(outputBec);
    }
    
    Public Shared Function CreateCustomSecurityBinding() As Binding
        Dim binding As New WSHttpBinding(SecurityMode.Message)
    
        With binding.Security.Message
            'Clients are anonymous to the service.
            .ClientCredentialType = MessageCredentialType.None
            'Secure conversation is turned off for simplification. If secure conversation is turned on, then 
            'you also need to set the IdentityVerifier on the secureconversation bootstrap binding.
            .EstablishSecurityContext = False
        End With
        ' Get the SecurityBindingElement and cast to a SymmetricSecurityBindingElement to set the IdentityVerifier.
        Dim outputBec = binding.CreateBindingElements()
        Dim ssbe = CType(outputBec.Find(Of SecurityBindingElement)(), SymmetricSecurityBindingElement)
    
        'Set the Custom IdentityVerifier.
        ssbe.LocalClientSettings.IdentityVerifier = New CustomIdentityVerifier()
    
        Return New CustomBinding(outputBec)
    End Function
    
  5. Mit der benutzerdefinierten Bindung, die zurückgegeben wird, wird eine Instanz des Clients und der Klasse erstellt.The custom binding that is returned is used to create an instance of the client and class. Der Client kann anschließend eine benutzerdefinierte Identitätsprüfung des Diensts gemäß der Anzeige im folgenden Code ausführen.The client can then perform a custom identity verification check of the service as shown in the following code.

    using (CalculatorClient client = new CalculatorClient(customSecurityBinding, serviceAddress))
    {
    
    Using client As New CalculatorClient(customSecurityBinding, serviceAddress)
    

BeispielExample

Im folgenden Beispiel wird eine vollständige Implementierung der IdentityVerifier-Klasse gezeigt.The following example shows a complete implementation of the IdentityVerifier class.

class CustomIdentityVerifier : IdentityVerifier
{
    public override bool CheckAccess(EndpointIdentity identity, AuthorizationContext authContext)
    {
        bool returnvalue = false;

        foreach (ClaimSet claimset in authContext.ClaimSets)
        {
            foreach (Claim claim in claimset)
            {
                if (claim.ClaimType == "http://schemas.microsoft.com/ws/2005/05/identity/claims/x500distinguishedname")
                {
                    X500DistinguishedName name = (X500DistinguishedName)claim.Resource;
                    if (name.Name.Contains(((OrgEndpointIdentity)identity).OrganizationClaim))
                    {
                        Console.WriteLine("Claim Type: {0}", claim.ClaimType);
                        Console.WriteLine("Right: {0}", claim.Right);
                        Console.WriteLine("Resource: {0}", claim.Resource);
                        Console.WriteLine();
                        returnvalue = true;
                    }
                }
            }

        }
        return returnvalue;
    }

    public override bool TryGetIdentity(EndpointAddress reference, out EndpointIdentity identity)
    {
        return IdentityVerifier.CreateDefault().TryGetIdentity(reference, out identity);
    }
}
Friend Class CustomIdentityVerifier
    Inherits IdentityVerifier

    Public Overrides Function CheckAccess(ByVal identity As EndpointIdentity, _
                                          ByVal authContext As AuthorizationContext) As Boolean

        Dim returnvalue = False
        For Each claimset In authContext.ClaimSets
            For Each claim In claimset
                If claim.ClaimType = "http://schemas.microsoft.com/ws/2005/05/identity/claims/x500distinguishedname" Then
                    Dim name = CType(claim.Resource, X500DistinguishedName)
                    If name.Name.Contains((CType(identity, OrgEndpointIdentity)).OrganizationClaim) Then
                        Console.WriteLine("Claim Type: {0}", claim.ClaimType)
                        Console.WriteLine("Right: {0}", claim.Right)
                        Console.WriteLine("Resource: {0}", claim.Resource)
                        Console.WriteLine()
                        returnvalue = True
                    End If
                End If
            Next claim
        Next claimset
        Return returnvalue

    End Function

    Public Overrides Function TryGetIdentity(ByVal reference As EndpointAddress, _
                                             <System.Runtime.InteropServices.Out()> ByRef identity As EndpointIdentity) As Boolean
        Return IdentityVerifier.CreateDefault().TryGetIdentity(reference, identity)
    End Function

End Class

BeispielExample

Im folgenden Beispiel wird eine vollständige Implementierung der EndpointIdentity-Klasse gezeigt.The following example shows a complete implementation of the EndpointIdentity class.

public class OrgEndpointIdentity : EndpointIdentity
{
    private string orgClaim;
    public OrgEndpointIdentity(string orgName)
    {
        orgClaim = orgName;
    }

    public string OrganizationClaim
    {
        get { return orgClaim; }
        set { orgClaim = value; }
    }
}
Public Class OrgEndpointIdentity
    Inherits EndpointIdentity
    Private orgClaim As String

    Public Sub New(ByVal orgName As String)
        orgClaim = orgName
    End Sub

    Public Property OrganizationClaim() As String
        Get
            Return orgClaim
        End Get
        Set(ByVal value As String)
            orgClaim = value
        End Set
    End Property
End Class

Siehe auchSee Also

ServiceAuthorizationManager
EndpointIdentity
IdentityVerifier
DienstidentitätsbeispielService Identity Sample
AutorisierungsrichtlinieAuthorization Policy
AutorisierungsrichtlinieAuthorization Policy