PrincipalPermissionMode 枚举

定义

设置使用 PrincipalPermissionAttribute 对方法访问进行控制时所执行的授权检查的模式。Sets the mode for authorization checks when using the PrincipalPermissionAttribute to control access to a method.

public enum class PrincipalPermissionMode
public enum PrincipalPermissionMode
type PrincipalPermissionMode = 
Public Enum PrincipalPermissionMode
继承
PrincipalPermissionMode

字段

Always 4

始终允许用户为 IPrincipal 指定 CurrentPrincipal 类。Always enables the user to specify a IPrincipal class for CurrentPrincipal.

Custom 3

使用户能够为 IPrincipal 指定自定义 CurrentPrincipal 类。Enables the user to specify a custom IPrincipal class for CurrentPrincipal.

None 0

未设置 CurrentPrincipalCurrentPrincipal is not set.

UseAspNetRoles 2

CurrentPrincipal 的设置是基于 ASP.NETASP.NET 角色提供程序 (RoleProvider) 进行的。CurrentPrincipal is set based on the ASP.NETASP.NET role provider (RoleProvider).

UseWindowsGroups 1

CurrentPrincipal 的设置是基于 Windows (WindowsPrincipal) 进行的。CurrentPrincipal is set based on Windows (WindowsPrincipal). 如果用户标识不与 Windows 帐户关联,则将使用匿名 Windows 用户。If the user identity is not associated with a Windows account, anonymous Windows is used.

示例

下面的示例演示如何指定 UseAspNetRoles。The following example shows how to specify UseAspNetRoles.

namespace TestPrincipalPermission
{
    class PrincipalPermissionModeWindows
    {
    
        [ServiceContract]
        interface ISecureService
        {
            [OperationContract]
            string Method1();
        }
                
        class SecureService : ISecureService
        {
            [PrincipalPermission(SecurityAction.Demand, Role = "everyone")]
            public string Method1()
            {
                return String.Format("Hello, \"{0}\"", Thread.CurrentPrincipal.Identity.Name);
            }
        }

        public void Run()
        {
            Uri serviceUri = new Uri(@"http://localhost:8006/Service");
            ServiceHost service = new ServiceHost(typeof(SecureService));
            service.AddServiceEndpoint(typeof(ISecureService), GetBinding(), serviceUri);
            service.Authorization.PrincipalPermissionMode = PrincipalPermissionMode.UseAspNetRoles;
            service.Open();

            EndpointAddress sr = new EndpointAddress(
                serviceUri, EndpointIdentity.CreateUpnIdentity(WindowsIdentity.GetCurrent().Name));
            ChannelFactory<ISecureService> cf = new ChannelFactory<ISecureService>(GetBinding(), sr);
            ISecureService client = cf.CreateChannel();
            Console.WriteLine("Client received response from Method1: {0}", client.Method1());
            ((IChannel)client).Close();
            Console.ReadLine();
            service.Close();
            
        }

        public static Binding GetBinding()
        {
            WSHttpBinding binding = new WSHttpBinding(SecurityMode.Message);
            binding.Security.Message.ClientCredentialType = MessageCredentialType.Windows;
            return binding;
        }
    }
}
Namespace TestPrincipalPermission
    Friend Class PrincipalPermissionModeWindows

        <ServiceContract> _
        Private Interface ISecureService
            <OperationContract> _
            Function Method1() As String
        End Interface

        Private Class SecureService
            Implements ISecureService
            <PrincipalPermission(SecurityAction.Demand, Role:="everyone")> _
            Public Function Method1() As String Implements ISecureService.Method1
                Return String.Format("Hello, ""{0}""", Thread.CurrentPrincipal.Identity.Name)
            End Function

        End Class

        Public Sub Run()
            Dim serviceUri As New Uri("http://localhost:8006/Service")
            Dim service As New ServiceHost(GetType(SecureService))
            service.AddServiceEndpoint(GetType(ISecureService), GetBinding(), serviceUri)
            service.Authorization.PrincipalPermissionMode = PrincipalPermissionMode.UseAspNetRoles
            service.Open()

            Dim sr As New EndpointAddress(serviceUri, EndpointIdentity.CreateUpnIdentity(WindowsIdentity.GetCurrent().Name))
            Dim cf As New ChannelFactory(Of ISecureService)(GetBinding(), sr)
            Dim client As ISecureService = cf.CreateChannel()
            Console.WriteLine("Client received response from Method1: {0}", client.Method1())
            CType(client, IChannel).Close()
            Console.ReadLine()
            service.Close()

        End Sub

        Public Shared Function GetBinding() As Binding
            Dim binding As New WSHttpBinding(SecurityMode.Message)
            binding.Security.Message.ClientCredentialType = MessageCredentialType.Windows
            Return binding
        End Function
    End Class
End Namespace

下面的示例演示如何指定自定义。The following example shows how to specify Custom.

namespace CustomMode
{
    public class Test
    {
        public static void Main()
        {
            try
            {
                ShowPrincipalPermissionModeCustom ppwm = new ShowPrincipalPermissionModeCustom();
                ppwm.Run();

            }
            catch (Exception exc)
            {
                Console.WriteLine("Error: {0}", exc.Message);
                Console.ReadLine();
            }
        }
    }

    class ShowPrincipalPermissionModeCustom
    {
        [ServiceContract]
        interface ISecureService
        {
            [OperationContract]
            string Method1(string request);
        }

        [ServiceBehavior]
        class SecureService : ISecureService
        {
            [PrincipalPermission(SecurityAction.Demand, Role = "everyone")]
            public string Method1(string request)
            {
                return String.Format("Hello, \"{0}\"", Thread.CurrentPrincipal.Identity.Name);
            }
        }

        public void Run()
        {
            Uri serviceUri = new Uri(@"http://localhost:8006/Service");
            ServiceHost service = new ServiceHost(typeof(SecureService));
            service.AddServiceEndpoint(typeof(ISecureService), GetBinding(), serviceUri);
            List<IAuthorizationPolicy> policies = new List<IAuthorizationPolicy>();
            policies.Add(new CustomAuthorizationPolicy());
            service.Authorization.ExternalAuthorizationPolicies = policies.AsReadOnly();
            service.Authorization.PrincipalPermissionMode = PrincipalPermissionMode.Custom;
            service.Open();

            EndpointAddress sr = new EndpointAddress(
                serviceUri, EndpointIdentity.CreateUpnIdentity(WindowsIdentity.GetCurrent().Name));
            ChannelFactory<ISecureService> cf = new ChannelFactory<ISecureService>(GetBinding(), sr);
            ISecureService client = cf.CreateChannel();
            Console.WriteLine("Client received response from Method1: {0}", client.Method1("hello"));
            ((IChannel)client).Close();
            Console.ReadLine();
            service.Close();            
        }

        public static Binding GetBinding()
        {
            WSHttpBinding binding = new WSHttpBinding(SecurityMode.Message);
            binding.Security.Message.ClientCredentialType = MessageCredentialType.Windows;
            return binding;
        }

        class CustomAuthorizationPolicy : IAuthorizationPolicy
        {
            string id = Guid.NewGuid().ToString();

            public string Id
            {
                get { return this.id; }
            }

            public ClaimSet Issuer
            {
                get { return ClaimSet.System; }
            }

            public bool Evaluate(EvaluationContext context, ref object state)
            {
                object obj;
                if (!context.Properties.TryGetValue("Identities", out obj))
                    return false;

                IList<IIdentity> identities = obj as IList<IIdentity>;
                if (obj == null || identities.Count <= 0)
                    return false;

                context.Properties["Principal"] = new CustomPrincipal(identities[0]);
                return true;
            }
        }

        class CustomPrincipal : IPrincipal
        {
            IIdentity identity;
            public CustomPrincipal(IIdentity identity)
            {
                this.identity = identity;
            }

            public IIdentity Identity
            {
                get { return this.identity; }
            }

            public bool IsInRole(string role)
            {
                return true;
            }
        }
    }
}
Namespace CustomMode
    Public Class Test
        Public Shared Sub Main()
            Try
                Dim ppwm As New ShowPrincipalPermissionModeCustom()
                ppwm.Run()

            Catch exc As Exception
                Console.WriteLine("Error: {0}", exc.Message)
                Console.ReadLine()
            End Try
        End Sub
    End Class

    Friend Class ShowPrincipalPermissionModeCustom
        <ServiceContract> _
        Private Interface ISecureService
            <OperationContract> _
            Function Method1(ByVal request As String) As String
        End Interface

        <ServiceBehavior> _
        Private Class SecureService
            Implements ISecureService
            <PrincipalPermission(SecurityAction.Demand, Role:="everyone")> _
            Public Function Method1(ByVal request As String) As String Implements ISecureService.Method1
                Return String.Format("Hello, ""{0}""", Thread.CurrentPrincipal.Identity.Name)
            End Function
        End Class

        Public Sub Run()
            Dim serviceUri As New Uri("http://localhost:8006/Service")
            Dim service As New ServiceHost(GetType(SecureService))
            service.AddServiceEndpoint(GetType(ISecureService), GetBinding(), serviceUri)
            Dim policies As New List(Of IAuthorizationPolicy)()
            policies.Add(New CustomAuthorizationPolicy())
            service.Authorization.ExternalAuthorizationPolicies = policies.AsReadOnly()
            service.Authorization.PrincipalPermissionMode = PrincipalPermissionMode.Custom
            service.Open()

            Dim sr As New EndpointAddress(serviceUri, EndpointIdentity.CreateUpnIdentity(WindowsIdentity.GetCurrent().Name))
            Dim cf As New ChannelFactory(Of ISecureService)(GetBinding(), sr)
            Dim client As ISecureService = cf.CreateChannel()
            Console.WriteLine("Client received response from Method1: {0}", client.Method1("hello"))
            CType(client, IChannel).Close()
            Console.ReadLine()
            service.Close()
        End Sub

        Public Shared Function GetBinding() As Binding
            Dim binding As New WSHttpBinding(SecurityMode.Message)
            binding.Security.Message.ClientCredentialType = MessageCredentialType.Windows
            Return binding
        End Function

        Private Class CustomAuthorizationPolicy
            Implements IAuthorizationPolicy
            Private id_Renamed As String = Guid.NewGuid().ToString()

            Public ReadOnly Property Id() As String Implements System.IdentityModel.Policy.IAuthorizationComponent.Id
                Get
                    Return Me.id_Renamed
                End Get
            End Property

            Public ReadOnly Property Issuer() As ClaimSet Implements IAuthorizationPolicy.Issuer
                Get
                    Return ClaimSet.System
                End Get
            End Property

            Public Function Evaluate(ByVal context As EvaluationContext, ByRef state As Object) As Boolean Implements IAuthorizationPolicy.Evaluate
                Dim obj As Object = Nothing
                If (Not context.Properties.TryGetValue("Identities", obj)) Then
                    Return False
                End If

                Dim identities As IList(Of IIdentity) = TryCast(obj, IList(Of IIdentity))
                If obj Is Nothing OrElse identities.Count <= 0 Then
                    Return False
                End If

                context.Properties("Principal") = New CustomPrincipal(identities(0))
                Return True
            End Function
        End Class

        Private Class CustomPrincipal
            Implements IPrincipal
            Private identity_Renamed As IIdentity
            Public Sub New(ByVal identity As IIdentity)
                Me.identity_Renamed = identity
            End Sub

            Public ReadOnly Property Identity() As IIdentity Implements IPrincipal.Identity
                Get
                    Return Me.identity_Renamed
                End Get
            End Property

            Public Function IsInRole(ByVal role As String) As Boolean Implements IPrincipal.IsInRole
                Return True
            End Function
        End Class
    End Class
End Namespace

注解

如果将 PrincipalPermissionAttribute 应用到方法,此模式将会指定授权访问时要用的一组角色。When applying the PrincipalPermissionAttribute to a method, this mode specifies which set of roles to use when authorizing access. 默认情况下,该属性使用 Windows 组(例如 AdministratorUsers)来指定用户必须所属的角色。By default, the attribute uses Windows groups (such as Administrator or Users) to specify the role to which the user must belong.

若要通过编程方式设置该模式,请创建 ServiceHost 类的实例,然后在它的行为集合中查找 ServiceAuthorizationBehavior,并将 PrincipalPermissionMode 设置为相应的枚举。To set the mode programmatically, create an instance of the ServiceHost class, then find the ServiceAuthorizationBehavior in its collection of behaviors, and set the PrincipalPermissionMode to the appropriate enumeration. 下面的示例将属性设置为 UseAspNetRoles。The following example sets the property to UseAspNetRoles.

ServiceHost myServiceHost = new ServiceHost(typeof(Calculator), baseUri);
ServiceAuthorizationBehavior myServiceBehavior =
    myServiceHost.Description.Behaviors.Find<ServiceAuthorizationBehavior>();
myServiceBehavior.PrincipalPermissionMode =
    PrincipalPermissionMode.UseAspNetRoles;
Dim myServiceHost As New ServiceHost(GetType(Calculator), baseUri)
Dim myServiceBehavior As ServiceAuthorizationBehavior = myServiceHost.Description.Behaviors.Find(Of ServiceAuthorizationBehavior)()
myServiceBehavior.PrincipalPermissionMode = PrincipalPermissionMode.UseAspNetRoles

还可以通过将 <serviceAuthorization> 添加到配置文件的 <serviceBehaviors> 来设置配置中的行为, 如以下代码所示。You can also set the behavior in configuration by adding a <serviceAuthorization> to the <serviceBehaviors> of a configuration file, as shown in the following code.

// Only a client authenticated with a valid certificate that has the 
// specified subject name and thumbprint can call this method.
[PrincipalPermission(SecurityAction.Demand,
     Name = "CN=ReplaceWithSubjectName; 123456712345677E8E230FDE624F841B1CE9D41E")]
public double Multiply(double a, double b)
{
    return a * b;
}
' Only a client authenticated with a valid certificate that has the 
' specified subject name and thumbprint can call this method.
<PrincipalPermission(SecurityAction.Demand, Name := "CN=ReplaceWithSubjectName; 123456712345677E8E230FDE624F841B1CE9D41E")> _
Public Function Multiply(ByVal a As Double, ByVal b As Double) As Double
    Return a * b
End Function

PrincipalPermissionAttribute 属性应用到方法时,枚举会影响该属性向用户授权的方式。The enumeration affects how the PrincipalPermissionAttribute attribute authorizes a user when it is applied to a method. 下面的示例将该属性应用到了方法,并且要求用户属于该计算机上的 Users 组。The following example applies the attribute to a method and demands that the user belong to the Users group on the computer. 只有将 PrincipalPermissionMode 设置为 UseWindowsGroup(默认设置)时,此代码才起作用。This code works only when the PrincipalPermissionMode is set to UseWindowsGroup (the default setting).

// Only members of the CalculatorClients group can call this method.
[PrincipalPermission(SecurityAction.Demand, Role = "Users")]
public double Add(double a, double b)
{
    return a + b;
}
' Only members of the CalculatorClients group can call this method.
<PrincipalPermission(SecurityAction.Demand, Role := "Users")> _
Public Function Add(ByVal a As Double, ByVal b As Double) As Double
    Return a + b
End Function

UseAspNetRolesUseAspNetRoles

UseAspNetRoles 值用于所有凭据类型。The UseAspNetRoles value is used for all credential types. 此模式允许 Windows Communication Foundation (WCF) 使用 ASP.NET 角色提供程序来做出授权决策。This mode enables Windows Communication Foundation (WCF) to use the ASP.NET role provider to make authorization decisions.

如果服务的凭据为 X.509 证书,则可以将 NamePrincipalPermissionAttribute 属性设置为由“主题”字段和“指纹”字段的串联值组成的字符串,如下面的示例所示。When the credential for a service is an X.509 certificate, you can set the Name property of the PrincipalPermissionAttribute to a string that consists of the concatenated values of the Subject field and the Thumbprint field, as shown in the following example.

ServiceHost myServiceHost = new ServiceHost(typeof(Calculator), baseUri);
ServiceAuthorizationBehavior myServiceBehavior =
    myServiceHost.Description.Behaviors.Find<ServiceAuthorizationBehavior>();
myServiceBehavior.PrincipalPermissionMode =
    PrincipalPermissionMode.UseAspNetRoles;
MyServiceAuthorizationManager sm = new MyServiceAuthorizationManager();
myServiceBehavior.ServiceAuthorizationManager = sm;
Dim myServiceHost As New ServiceHost(GetType(Calculator), baseUri)
Dim myServiceBehavior As ServiceAuthorizationBehavior = myServiceHost.Description.Behaviors.Find(Of ServiceAuthorizationBehavior)()
myServiceBehavior.PrincipalPermissionMode = PrincipalPermissionMode.UseAspNetRoles
Dim sm As New MyServiceAuthorizationManager()
myServiceBehavior.ServiceAuthorizationManager = sm

该串联字符串由用分号和空格分隔的主题值和指纹值组成。The concatenated string consists of the subject and thumbprint values separated by a semicolon and a space.

还可以将证书的“主题”字段设置为空字符串。It is also possible for a certificate to have a Subject field set to a null string. 在这种情况下,可以将 Name 属性设置为分号,后跟空格,然后是指纹,如下面的示例所示。In that case, you can set the Name property to a semicolon followed by a space and then the thumbprint, as shown in the following example.

// Only a client authenticated with a valid certificate that has the 
// specified thumbprint can call this method.
[PrincipalPermission(SecurityAction.Demand,
     Name = "; 123456712345677E8E230FDE624F841B1CE9D41E")]
public double Divide(double a, double b)
{
    return a * b;
}
' Only a client authenticated with a valid certificate that has the 
' specified thumbprint can call this method.
<PrincipalPermission(SecurityAction.Demand, Name := "; 123456712345677E8E230FDE624F841B1CE9D41E")> _
Public Function Divide(ByVal a As Double, ByVal b As Double) As Double
    Return a * b
End Function

如果存在 ASP.NET 角色提供程序,则还可以将 Role 属性设置为数据库中的角色。If an ASP.NET role provider is present, you can also set the Role property to a role in the database. 默认情况下,数据库由 SqlRoleProvider 表示。By default, the database is represented by the SqlRoleProvider. 您还可以利用 RoleProvider 类的 ServiceAuthorizationBehavior 属性来设置自定义角色提供程序。You can also set a custom role provider with the RoleProvider property of the ServiceAuthorizationBehavior class. 下面的代码将该角色设置为了 AdministratorsThe following code sets the role to Administrators. 请注意,角色提供程序必须将用户帐户映射到该角色。Note that the role provider must map the user account to that role.

[PrincipalPermission(SecurityAction.Demand, Role = "Administrators")]
public string ReadFile(string fileName)
{
    // Code not shown.
    return "Not implemented";
}
<PrincipalPermission(SecurityAction.Demand, Role := "Administrators")> _
Public Function ReadFile(ByVal fileName As String) As String
    ' Code not shown.
    Return "Not implemented"
End Function

有关 ASP.NET 角色提供程序的详细信息, 请参阅如何:使用 ASP.NET 2.0中的角色管理器。For more information about the ASP.NET Role provider, see How To: Use Role Manager in ASP.NET 2.0.

有关使用 WCF 和角色提供程序的详细信息, 请参阅如何:将 ASP.NET 角色提供程序用于服务For more information about using WCF and the role provider, see How to: Use the ASP.NET Role Provider with a Service.

自定义Custom

当属性设置为 custom 时, 还必须提供实现IAuthorizationPolicy类的自定义类。When the property is set to Custom, you must also provide a custom class that implements the IAuthorizationPolicy class. 此类负责提供 IPrincipal 集合内调用方的 Properties 表示形式。This class is responsible for providing the caller's IPrincipal representation inside the Properties collection. 它必须使用“Principal”字符串关键字将 IPrincipal 实例存储到属性集合中,如下面的示例所示。It must store the IPrincipal instance to the properties collection using the "Principal" string key, as shown in the following example.

evaluationContext.Properties["Principal"]=new CustomPrincipal(identity);  

背景Background

.NET Framework.NET Framework 中基于角色的安全性使得应用程序可以通过代码指定授权。The role-based security in .NET Framework.NET Framework enables applications to specify authorizations through code. 指定 PrincipalPermission 请求后,CurrentPrincipal 必须满足 PrincipalPermission 要求。By specifying the PrincipalPermission demand, the CurrentPrincipal must satisfy the PrincipalPermission requirement. 例如,用户必须为特定的角色或位于特定的组中。For example, that the user must be in a specific role or group. 否则,线程将无权执行代码,这会导致异常。Otherwise, the thread is not authorized to execute the code, which results in an exception. WCF 提供了一组PrincipalPermissionMode选项, 用于根据CurrentPrincipal SecurityContext相应的具体情况指定。WCF provides a set of PrincipalPermissionMode selections to specify the CurrentPrincipal based on SecurityContext accordingly.

适用于