Практическое руководство. Сравнение утверждений

Инфраструктура модели удостоверений в Windows Communication Foundation (WCF) используется для выполнения проверка авторизации. По существу общей задачей является сравнение утверждений в контексте авторизации с утверждениями, необходимыми для выполнения затребованного действия или доступа к затребованному ресурсу. В этом разделе описывается сравнение утверждений, включая встроенные и пользовательские типы утверждений. Дополнительные сведения о инфраструктуре модели удостоверений см. в разделе "Управление утверждениями и авторизацией" с помощью модели удостоверений.

При сравнении утверждений сравниваются три элемента одного утверждения (тип, право и ресурс) с аналогичными элементами другого утверждения, чтобы определить, одинаковы ли они. См. следующий пример.

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

Оба утверждения будут иметь тип имени Name, право свойства PossessProperty и ресурс строки «someone». Поскольку все три элемента утверждения одинаковы, сами утверждения одинаковы.

Встроенные типы утверждений сравниваются с помощью метода Equals. При необходимости используется код сравнения, зависящий от утверждений. Например, учитывая следующие два утверждения субъекта-пользователя (UPN), код сравнения в Equals методе возвращается true, при условии example\someone , что он определяет того же пользователя домена, что 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")

Пользовательские типы утверждений также могут сравниваться с помощью метода Equals. Однако в тех случаях, когда тип, возвращенный свойством Resource утверждения, несколько отличается от типа-примитива, метод Equals возвращает значение true, только если значения, возвращенные свойствами Resource, одинаковы для каждого метода Equals. В других случаях пользовательский тип, возвращенный свойством Resource, должен переопределить методы Equals и GetHashCode, чтобы выполнить любую необходимую пользовательскую обработку.

Сравнение встроенных утверждений

  1. Пусть заданы два экземпляра класса Claim. Используйте метод Equals для выполнения сравнения, как показано в следующем коде.

    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
    

Сравнение пользовательских утверждений с типами-примитивами ресурсов

  1. Для пользовательских утверждений с типами-примитивами ресурсов сравнение может выполняться аналогично сравнению для встроенных утверждений, как показано в следующем коде.

    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. Для пользовательских утверждений с типами ресурсов на основе структур или классов тип ресурса должен переопределить метод Equals.

  3. Сначала проверьте, имеет ли параметр obj значение null. Если да, верните значение false.

    if (obj == null) return false;
    
    If obj Is Nothing Then
        Return False
    
  4. Затем вызовите метод ReferenceEquals и передайте this и obj в качестве параметров. Если этот метод возвращает значение true, верните значение true.

    if (ReferenceEquals(this, obj)) return true;
    
    If ReferenceEquals(Me, obj) Then
        Return True
    
  5. Затем попытайтесь присвоить значение obj локальной переменной типа класса. Если эта попытка завершается неуспешно, ссылка имеет значение null. В этом случае верните значение false.

  6. Выполните пользовательское сравнение, необходимое для правильного сравнения текущего утверждения с предоставленным утверждением.

Пример

В следующем примере показано сравнение пользовательских утверждений, где ресурсом утверждения является тип, отличный от типа-примитива.

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

См. также