PrincipalPermissionMode Перечисление
Определение
Важно!
Некоторые сведения относятся к предварительной версии продукта, в которую до выпуска могут быть внесены существенные изменения. Майкрософт не предоставляет никаких гарантий, явных или подразумеваемых, относительно приведенных здесь сведений.
Задает режим проверки авторизации при использовании PrincipalPermissionAttribute для управления доступом к методу.
public enum class PrincipalPermissionMode
public enum PrincipalPermissionMode
type PrincipalPermissionMode =
Public Enum PrincipalPermissionMode
- Наследование
Поля
Always | 4 | Всегда позволяет пользователю указать класс IPrincipal для CurrentPrincipal. |
Custom | 3 | Позволяет пользователю указать настраиваемый класс IPrincipal для CurrentPrincipal. |
None | 0 | CurrentPrincipal не задано. |
UseAspNetRoles | 2 | CurrentPrincipal задается на основе поставщика роли ASP.NET (RoleProvider). |
UseWindowsGroups | 1 | CurrentPrincipal задан на основе Windows WindowsPrincipal (). Если идентификация пользователя не связана с учетной записью Windows, используется анонимный вход Windows. |
Примеры
В следующем примере показано, как указать 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
В следующем примере показано, как указать 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 к методу, с помощью этого режима можно указать, какой набор ролей следует использовать при авторизации доступа. По умолчанию атрибут использует группы Windows (например, Administrator
или Users
) для указания роли, к которой должен принадлежать пользователь.
Чтобы задать режим программно, необходимо создать экземпляр класса ServiceHost
, найти ServiceAuthorizationBehavior в его коллекции расширений функциональности и задать PrincipalPermissionMode для соответствующего перечисления. В следующем примере свойству присваивается значение 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> файла конфигурации, как показано в следующем коде.
// 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 при применении этого атрибута к методу. В следующем примере показано, как применить атрибут к методу. Для этого необходимо, чтобы пользователь принадлежал к группе «Пользователи» на компьютере. Данный код работает только в том случае, если PrincipalPermissionMode имеет значение UseWindowsGroup
(по умолчанию).
// 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
UseAspNetRoles
Значение UseAspNetRoles используется для всех типов учетных данных. Этот режим позволяет Windows Communication Foundation (WCF) использовать поставщик ролей ASP.NET для принятия решений об авторизации.
Если для службы в качестве учетных данных используется сертификат X.509, можно присвоить свойству Name
для PrincipalPermissionAttribute строковое значение, которое включает составные значение полей «Тема» и «Отпечаток пальца», как показано в следующем примере кода.
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
Составное строковое значение состоит из значений темы и отпечатка пальца, разделенных точкой с запятой и пробелом.
Возможно также использовать пустую строку в поле «Тема» в сертификате. В этом случае можно задать свойство Name
как точку с запятой, за которой следует пробел, а затем значение отпечатка пальца, как показано в следующем примере кода.
// 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 роль в базе данных. По умолчанию база данных представлена SqlRoleProvider. Также можно задать настраиваемый поставщик ролей с помощью свойства RoleProvider класса ServiceAuthorizationBehavior. В следующем примере кода показано, как присвоить роли значение Administrators
. Следует учесть, что поставщик ролей должен сопоставлять учетную запись пользователя с данной ролью.
[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
Дополнительные сведения об использовании WCF и поставщика ролей см. в разделе Практическое руководство. Использование поставщика ролей ASP.NET со службой.
Особые настройки
Если свойству присвоено значение Custom, необходимо также предоставить пользовательский класс, реализующий IAuthorizationPolicy класс . Этот класс обеспечивает представление вызывающего оператора IPrincipal
в коллекции Properties. Экземпляр IPrincipal
должен сохраняться в коллекции свойств с помощью строкового ключа «Главный», как показано в следующем примере.
evaluationContext.Properties["Principal"]=new CustomPrincipal(identity);
Фон
Безопасность на основе ролей в платформа .NET Framework позволяет приложениям указывать авторизацию с помощью кода. Если задано требование PrincipalPermission, CurrentPrincipal должен соответствовать требованиям PrincipalPermission
. Например, пользователь должен принадлежать к определенной роли или группе. В противном случае поток не будет авторизован для выполнения кода и возникнет исключение. WCF предоставляет набор вариантов выбора для соответствующего PrincipalPermissionModeCurrentPrincipalSecurityContext указания .