Como: comparar declarações

A Infraestrutura do Modelo de Identidade do WCF (Windows Communication Foundation) é usada para executar a verificação de autorização. Assim, uma tarefa comum é comparar as declarações no contexto de autorização com as declarações necessárias para executar a ação solicitada ou acessar o recurso solicitado. Este tópico descreve como comparar declarações, incluindo tipos de declarações internas e personalizadas. Para obter mais informações sobre a Infraestrutura do Modelo de Identidade, confira Como gerenciar as declarações e a autorização com o modelo de identidade.

A comparação de declarações envolve comparar as três partes de uma declaração (tipo, direito e recurso) com as mesmas partes em outra declaração para ver se elas são iguais. Veja o exemplo a seguir.

Claim c1 = Claim.CreateNameClaim("someone");
Claim c2 = Claim.CreateNameClaim("someone");
Dim c1 As Claim = Claim.CreateNameClaim("someone")
Dim c2 As Claim = Claim.CreateNameClaim("someone")

As duas declarações têm um tipo de declaração igual a Name, um direito de PossessProperty e um recurso da cadeia de caracteres "someone". Como as três partes da declaração são iguais, as próprias declarações são iguais.

Os tipos de declaração internos são comparados com o método Equals. O código de comparação específico da declaração é usado quando necessário. Por exemplo, considerando as duas declarações UPN (nome principal do usuário), o código de comparação no método Equals retorna true, supondo que example\someone identifique o mesmo usuário de domínio que someone@example.com.

Claim c1 = Claim.CreateUpnClaim("someone@example.com");
Claim c2 = Claim.CreateUpnClaim("example\\someone");
Dim c1 As Claim = Claim.CreateUpnClaim("someone@example.com")
Dim c2 As Claim = Claim.CreateUpnClaim("example\someone")

Os tipos de declaração personalizados também podem ser comparados com o método Equals. No entanto, nos casos em que o tipo retornado pela propriedade Resource da declaração é algo diferente de um tipo primitivo, o Equals retorna true somente se os valores retornados pelas propriedades Resource são iguais de acordo com o método Equals. Nos casos em que isso não é apropriado, o tipo personalizado retornado pela propriedade Resource deve substituir os métodos Equals e GetHashCode para executar o processamento personalizado necessário.

Como comparar declarações internas

  1. Considerando duas instâncias da classe Claim, use a Equals para fazer a comparação, conforme mostrado no código a seguir.

    public bool CompareTwoClaims(Claim c1, Claim c2)
    {
        return c1.Equals(c2);
    }
    
    Public Function CompareTwoClaims(ByVal c1 As Claim, ByVal c2 As Claim) As Boolean
        Return c1.Equals(c2)
    End Function
    

Como comparar declarações personalizadas com tipos de recursos primitivos

  1. Para declarações personalizadas com tipos de recursos primitivos, a comparação pode ser executada como para declarações internas, conforme mostrado no código a seguir.

    public bool CompareTwoClaims(Claim c1, Claim c2)
    {
        return c1.Equals(c2);
    }
    
    Public Function CompareTwoClaims(ByVal c1 As Claim, _
    ByVal c2 As Claim) As Boolean
        Return c1.Equals(c2)
    
    End Function
    
  2. Para declarações personalizadas com tipos de recursos baseados em estrutura ou classe, o tipo de recurso deve substituir o método Equals.

  3. Primeiro, verifique se o parâmetro obj é null e, nesse caso, retorne false.

    if (obj == null) return false;
    
    If obj Is Nothing Then
        Return False
    
  4. A seguir, chame ReferenceEquals e transmita this e obj como parâmetros. Se ele retornar true, retorne true.

    if (ReferenceEquals(this, obj)) return true;
    
    If ReferenceEquals(Me, obj) Then
        Return True
    
  5. Depois, tente atribuir obj a uma variável local do tipo de classe. Se isso falhar, a referência será null. Nesses casos, retorne false.

  6. Execute a comparação personalizada necessária para comparar corretamente a declaração atual com a declaração fornecida.

Exemplo

O exemplo a seguir mostra uma comparação de declarações personalizadas em que o recurso de declaração é um tipo não primitivo.

using System;
using System.IdentityModel.Claims;

namespace Samples
{
    public sealed class MyResourceType
    {
        // private members
        private string text;
        private int number;

        // Constructors
        public MyResourceType()
        {
        }

        public MyResourceType(string text, int number)
        {
            this.text = text;
            this.number = number;
        }

        // Public properties
        public string Text { get { return this.text; } }
        public int Number { get { return this.number; } }

        // Override Object.Equals to perform specific comparison
        public override bool Equals(Object obj)
        {
            // If the object we're being asked to compare ourselves to is null
            // then return false
            if (obj == null)
                return false;

            // If the object we're being asked to compare ourselves to is us
            // then return true
            if (ReferenceEquals(this, obj))
                return true;

            // Try to convert the object we're being asked to compare ourselves to
            // into an instance of MyResourceType
            MyResourceType rhs = obj as MyResourceType;

            // If the object we're being asked to compare ourselves to
            // isn't an instance of MyResourceType then return false
            if (rhs == null)
                return false;

            // Return true if our members are the same as those of the object
            // we're being asked to compare ourselves to. Otherwise return false
            return (this.text == rhs.text && this.number == rhs.number);
        }

        public override int GetHashCode()
        {
            return (this.text.GetHashCode() ^ this.number.GetHashCode());
        }
    }

    class Program
    {
        public static void Main()
        {
            // Create two claims
            Claim c1 = new Claim("http://example.org/claims/mycustomclaim",
                new MyResourceType("Martin", 38), Rights.PossessProperty);
            Claim c2 = new Claim("http://example.org/claims/mycustomclaim",
                new MyResourceType("Martin", 38), Rights.PossessProperty);

            // Compare the claims
            if (c1.Equals(c2))
                Console.WriteLine("Claims are equal");
            else
                Console.WriteLine("Claims are not equal");
        }
    }
}
Imports System.IdentityModel.Claims
Imports System.Security.Permissions

NotInheritable Public Class MyResourceType
    ' private members
    Private textValue As String
    Private numberValue As Integer


    ' Constructors
    Public Sub New()

    End Sub

    Public Sub New(ByVal textVal As String, ByVal numberValue As Integer)
        Me.textValue = textVal
        Me.numberValue = numberValue

    End Sub

    ' Public properties

    Public ReadOnly Property Text() As String
        Get
            Return Me.textValue
        End Get
    End Property

    Public ReadOnly Property Number() As Integer
        Get
            Return Me.numberValue
        End Get
    End Property
    ' Override Object.Equals to perform a specific comparison.
    Public Overrides Function Equals(ByVal obj As [Object]) As Boolean
        ' If the object being compared to is null then return false.
        If obj Is Nothing Then
            Return False
        End If
        ' If the object we are being asked to compare ourselves to is us
        ' then return true.
        If ReferenceEquals(Me, obj) Then
            Return True
        End If
        ' Try to convert the object we are being asked to compare ourselves to
        ' into an instance of MyResourceType.
        Dim rhs As MyResourceType = CType(obj, MyResourceType)

        ' If the object being compared to is not an instance of 
        ' MyResourceType then return false.
        If rhs Is Nothing Then
            Return False
        End If
        ' Return true if members are the same as those of the object
        ' being asked to compare to; otherwise, return false.
        Return Me.textValue = rhs.textValue AndAlso Me.numberValue = rhs.numberValue

    End Function

    Public Overrides Function GetHashCode() As Integer
        Return Me.textValue.GetHashCode() ^ Me.numberValue.GetHashCode()

    End Function
End Class
Class Program

    Public Shared Sub Main()
        ' Create two claims.
        Dim c1 As New Claim("http://example.org/claims/mycustomclaim", _
           New MyResourceType("Martin", 38), Rights.PossessProperty)
        Dim c2 As New Claim("http://example.org/claims/mycustomclaim", _
           New MyResourceType("Martin", 38), Rights.PossessProperty)

        ' Compare the claims.
        If c1.Equals(c2) Then
            Console.WriteLine("Claims are equal")
        Else
            Console.WriteLine("Claims are not equal")
        End If

    End Sub
End Class

Confira também