PrincipalPermissionMode 列舉
定義
重要
部分資訊涉及發行前產品,在發行之前可能會有大幅修改。 Microsoft 對此處提供的資訊,不做任何明確或隱含的瑕疵擔保。
當使用 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 屬性在套用至方法時,授權使用者的方式。 下列範例會將此屬性套用至方法,並要求使用者屬於電腦上的 Users 群組。 這個程式碼只有在 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
串連字串是由以分號和空格隔開的主旨和指紋值所組成。
有的憑證可能會將 [主旨] 欄位設定為 null 字串。 在這種情況中,您可以將 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 表示法。 它必須使用 "Principal" 字串索引鍵將 IPrincipal
執行個體儲存至屬性集合,如下列範例所示。
evaluationContext.Properties["Principal"]=new CustomPrincipal(identity);
背景
.NET Framework中的角色型安全性可讓應用程式透過程式碼指定授權。 藉由指定 PrincipalPermission 要求,CurrentPrincipal 必須滿足 PrincipalPermission
需求。 例如,使用者必須屬於特定的角色或群組。 否則,執行緒不會獲得執行程式碼的授權,而造成例外狀況。 WCF 提供一組 PrincipalPermissionMode 選取專案,以據以 SecurityContext 指定 CurrentPrincipal 。