如何:比较声明
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
属性返回的自定义类型应该重写 Equals 和 GetHashCode 方法,以执行任何必要的自定义处理。
比较内置声明
给定 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
比较具有基元资源类型的自定义声明
对于具有基元资源类型的自定义声明,可以按照内置声明那样的方式执行比较,如下面的代码所示。
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
对于具有基于结构或类的资源类型的自定义声明,资源类型应重写 Equals 方法。
首先检查
obj
参数是否为null
,如果是,则返回false
。if (obj == null) return false;
If obj Is Nothing Then Return False
接下来调用 ReferenceEquals,并将
this
和obj
作为参数传递。 如果它返回true
,则返回true
。if (ReferenceEquals(this, obj)) return true;
If ReferenceEquals(Me, obj) Then Return True
然后尝试将
obj
分配给一个类类型的局部变量。 如果此操作失败,则引用为null
。 在这种情况下返回false
。执行将当前声明与提供的声明进行正确比较所需的自定义比较。
示例
下面的示例显示自定义声明的比较,其中声明资源是非基元类型。
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