Udostępnij za pośrednictwem


Instrukcje: tworzenie niestandardowego weryfikatora tożsamości klienta

Funkcja tożsamości programu Windows Communication Foundation (WCF) umożliwia klientowi wcześniejsze określenie oczekiwanej tożsamości usługi. Za każdym razem, gdy serwer uwierzytelnia się na kliencie, tożsamość jest sprawdzana względem oczekiwanej tożsamości. (Aby uzyskać wyjaśnienie tożsamości i sposobu jej działania, zobacz Tożsamość usługi i uwierzytelnianie).

W razie potrzeby weryfikację można dostosować przy użyciu niestandardowego weryfikatora tożsamości. Można na przykład przeprowadzić dodatkowe kontrole weryfikacji tożsamości usługi. W tym przykładzie weryfikator tożsamości niestandardowej sprawdza dodatkowe oświadczenia w certyfikacie X.509 zwróconym z serwera. Aby zapoznać się z przykładową aplikacją, zobacz Service Identity Sample (Przykład tożsamości usługi).

Aby rozszerzyć klasę EndpointIdentity

  1. Zdefiniuj nową klasę, która pochodzi z EndpointIdentity klasy . W tym przykładzie nazwa rozszerzenia OrgEndpointIdentity.

  2. Dodaj prywatne elementy członkowskie wraz z właściwościami, które będą używane przez klasę rozszerzoną IdentityVerifier do przeprowadzania sprawdzania tożsamości względem oświadczeń w tokenie zabezpieczającym zwróconym z usługi. W tym przykładzie zdefiniowano jedną właściwość: OrganizationClaim właściwość .

    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
    

Aby rozszerzyć klasę IdentityVerifier

  1. Zdefiniuj nową klasę, która pochodzi z klasy IdentityVerifier. W tym przykładzie nazwa rozszerzenia 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. Zastąpij metodę CheckAccess . Metoda określa, czy sprawdzanie tożsamości zakończyło się powodzeniem, czy niepowodzeniem.

  3. Metoda CheckAccess ma dwa parametry. Pierwszy to wystąpienie EndpointIdentity klasy . Drugi to wystąpienie AuthorizationContext klasy.

    W implementacji metody sprawdź kolekcję oświadczeń zwróconych przez ClaimSets właściwość AuthorizationContext klasy i wykonaj kontrole uwierzytelniania zgodnie z potrzebami. Ten przykład rozpoczyna się od znalezienia dowolnego oświadczenia o typie "Nazwa wyróżniająca", a następnie porównuje nazwę z rozszerzeniem 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
    

Aby zaimplementować metodę TryGetIdentity

  1. Zaimplementuj metodę TryGetIdentity , która określa, czy wystąpienie EndpointIdentity klasy może zostać zwrócone przez klienta. Infrastruktura WCF wywołuje najpierw implementację TryGetIdentity metody w celu pobrania tożsamości usługi z komunikatu. Następnie infrastruktura wywołuje implementację CheckAccess za pomocą zwróconych EndpointIdentity wartości i AuthorizationContext.

  2. W metodzie TryGetIdentity umieść następujący kod:

    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
    
    

Aby zaimplementować powiązanie niestandardowe i ustawić niestandardowy element IdentityVerifier

  1. Utwórz metodę zwracającą Binding obiekt. W tym przykładzie rozpoczyna się tworzenie wystąpienia WSHttpBinding klasy i ustawia jego tryb zabezpieczeń na Message, i na NoneClientCredentialType wartość .

  2. Utwórz element BindingElementCollection przy użyciu CreateBindingElements metody .

  3. Zwróć element SecurityBindingElement z kolekcji i rzutuj go do zmiennej SymmetricSecurityBindingElement .

  4. IdentityVerifier Ustaw właściwość LocalClientSecuritySettings klasy na nowe wystąpienie utworzonej CustomIdentityVerifier wcześniej klasy.

    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. Zwracane powiązanie niestandardowe służy do tworzenia wystąpienia klienta i klasy. Klient może następnie przeprowadzić niestandardową weryfikację tożsamości usługi, jak pokazano w poniższym kodzie.

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

Przykład 1

W poniższym przykładzie przedstawiono kompletną implementację IdentityVerifier klasy.

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

Przykład 2

W poniższym przykładzie przedstawiono kompletną implementację EndpointIdentity klasy.

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

Zobacz też