直接访问主体对象

更新:2007 年 11 月

尽管使用命令式和声明式请求调用基于角色的安全检查是检查和强制身份与角色成员条件的主要机制,但在某些情况下,您可能希望直接访问 Principal 对象及其关联的 Identity 对象来完成身份验证任务,而不必创建权限对象。例如,如果不希望验证失败时的默认行为是引发异常,则可能不想使用声明式或命令式请求。这时,可以在 System.Threading.Thread 类上使用静态 CurrentPrincipal 属性来访问 Principal 对象并调用其方法。

获取主体对象后,可以使用条件语句根据主体名来控制对代码的访问,如下面的代码示例所示。

WindowsPrincipal MyPrincipal = 
    (WindowsPrincipal)Thread.CurrentPrincipal;
if (MyPrincipal.Identity.Name == "fred") 
    // Permit access to some code. 
Dim MyPrincipal As WindowsPrincipal = _
    CType(Thread.CurrentPrincipal, WindowsPrincipal)
If (MyPrincipal.Identity.Name = "fred") Then
    ' Permit access to some code.
End If

还可通过在当前 Principal 对象上调用 IsInRole 方法,以编程方式检查角色成员条件,如以下代码实例所示。

// Get the current identity.
WindowsIdentity MyIdent = WindowsIdentity.GetCurrent();

// Create a principal.
WindowsPrincipal MyPrincipal = new WindowsPrincipal(MyIdent);

// Check the role using a string.
if (MyPrincipal.IsInRole(@"BUILTIN\Administrators"))
{
    Console.WriteLine("You are an administrator.");
}
else
{
    Console.WriteLine("You are not an administrator.");
}
// Check the role using an enumeration.
if (MyPrincipal.IsInRole(WindowsBuiltInRole.Administrator))
{
    Console.WriteLine("You are an administrator.");
}
else
{
    Console.WriteLine("You are not an administrator.");
}
' Get the current identity.
Dim MyIdent As WindowsIdentity = WindowsIdentity.GetCurrent()

' Create a principal.
Dim MyPrincipal As New WindowsPrincipal(MyIdent)

' Check the role using a string.
If MyPrincipal.IsInRole("BUILTIN\Administrators") Then
    Console.WriteLine("You are an administrator.")
Else
    Console.WriteLine("You are not an administrator.")
End If
' Check the role using an enumeration.
If MyPrincipal.IsInRole(WindowsBuiltInRole.Administrator) Then
    Console.WriteLine("You are an administrator.")
Else
    Console.WriteLine("You are not an administrator.")
End If

当希望访问应用程序定义的 Principal 对象特定的行为时可以使用此方法。但在大多数情况下,应使用 PrincipalPermission 类根据身份或角色成员身份来控制对代码的访问。

下面的代码示例将创建一个 WindowsPrincipal 对象和一个 WindowsIdentity 对象,将它们设置为当前用户,并根据 Principal 的值做出安全决定。此代码不以命令或声明的方式使用 PrincipalPermission 对象,而是根据主体对象的值做出访问决定。

using System;
using System.Security.Permissions;
using System.Security.Policy;
using System.Security.Principal;
using System.Threading;

public class Class1
{
    public static int Main(string[] args)
    {
        // Set principal policy to get a WindowsPrincipal 
        // as the current principal so you have permission to get 
        // current user information.
        AppDomain.CurrentDomain.SetPrincipalPolicy(
            PrincipalPolicy.WindowsPrincipal);

        // Get the current principal and put it into a principal object.
        WindowsPrincipal myPrincipal = (Thread.CurrentPrincipal 
            as WindowsPrincipal);

        // Check the name and see if the user is authenticated. 
        if (myPrincipal.Identity.Name.Equals(@"MYDOMAIN\myuser") 
            && myPrincipal.Identity.IsAuthenticated.Equals(true))
        {
            Console.WriteLine("Hello {0}, you are authenticated!", 
                myPrincipal.Identity.Name.ToString());
        }
        else
        {
            Console.WriteLine("Go away! You are not authorized!");
        }
        // Use IsInRole to determine the role of the current user.
        Array wbirFields = Enum.GetValues(typeof(WindowsBuiltInRole));
        foreach (object roleName in wbirFields)
        {
            try
            {
                Console.WriteLine("{0}? {1}.", roleName,
                    myPrincipal.IsInRole((WindowsBuiltInRole)roleName));
            }
            catch (Exception)
            {
                Console.WriteLine("{0}: Could not obtain role for this RID.",
                    roleName);
            }
        }
        return 0;
    }
}  
Imports System
Imports System.Security.Permissions
Imports System.Security.Policy
Imports System.Security.Principal
Imports System.Threading

Public Class Class1

    Public Shared Sub Main()
        ' Set principal policy to get a WindowsPrincipal 
        ' as the current principal so you have permission to get
        ' current user information.
        AppDomain.CurrentDomain.SetPrincipalPolicy( _
            PrincipalPolicy.WindowsPrincipal)

        ' Get the current principal and put it into a principal object.
        Dim MyPrincipal As WindowsPrincipal = _
            CType(Thread.CurrentPrincipal, WindowsPrincipal)

        ' Check the name and see if the user is authenticated. 
        If (MyPrincipal.Identity.Name.Equals("MYDOMAIN\myuser") _
            And MyPrincipal.Identity.IsAuthenticated) Then
            Console.WriteLine("Hello {0}, you are authenticated!", _
                MyPrincipal.Identity.Name.ToString())
        Else
            Console.WriteLine("Go away! You are not authorized!")
        End If
        ' Use IsInRole to determine the role of the current user.
        Dim wbirFields As Array = _
            [Enum].GetValues(GetType(WindowsBuiltInRole))

        Dim roleName As Object
        For Each roleName In wbirFields
            Try
                Console.WriteLine("{0}? {1}.", roleName, _
                    MyPrincipal.IsInRole(CType(roleName, _
                    WindowsBuiltInRole)))
            Catch
                Console.WriteLine( _
                    "{0}: Could not obtain the role for this RID.", _
                    roleName)
            End Try
        Next roleName
    End Sub
End Class

如果当前用户是 MYDOMAIN\myuser,此程序将向控制台显示以下消息。

Hello MYDOMAIN\myuser, you are authenticated!

但是,如果当前用户是任何其他用户,则程序将显示以下消息。

Go away! You are not authorized!

MyPrincipal.Identity.Name 中的值显示代表授权帐户的域和用户名。请注意,在 C# 中,字符串 "MYDOMAIN\myuser" 以 at 符号 (@) 为前缀,这样就不会将反斜杠解释为转义符。尽管前面的示例使用 WindowsIdentity 对象,但仍可使用一般对象轻松产生类似的代码。只需创建一般对象的实例,向其传递所需的值,然后就可以在该对象中检查那些值。

请参见

概念

基于角色的安全检查

参考

System.Threading.Thread.CurrentPrincipal