如何:比较声明

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) 声明,假定 example\someone 将同一域用户标识为 someone@example.com,则 Equals 方法中的比较代码会返回 true

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 属性返回的自定义类型应该重写 EqualsGetHashCode 方法,以执行任何必要的自定义处理。

比较内置声明

  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,并将 thisobj 作为参数传递。 如果它返回 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

另请参阅