如果应用于 Class,方法的 PrincipalPermission 将不起作用
PrincipalPermission on Method doesn't work if applied to Class
我的代码看起来像这样:
[PrincipalPermission(SecurityAction.Demand, Role = "RoleA")]
class Foo
{
[PrincipalPermission(SecurityAction.Demand, Role = "RoleB")]
public static bool Bar()
{
return true;
}
}
如果我尝试 运行 Foo.Bar();
如果我没有 RoleA,它将失败,但从不检查 RoleB。不管我有没有RoleB,只要有RoleA就可以。
如果我从 class 定义中删除 [PrincipalPermission(SecurityAction.Demand, Role = "RoleA")]
,那么它会按预期检查 RoleB。
我四处搜索,发现在两个不同的 SO 问题 (here and here) 中都提到了这个确切的问题,但在任何一种情况下都没有答案。有一条评论指向一个旧的 Microsoft Connect link,它应该包含答案,但没有评论或答案真正说明问题所在。
我真的非常感谢任何帮助。
多个 PrincipalPermissionAttribute 要求使用 OR 组合,因此在您的情况下:
- RoleA 可以构造 class 的实例并调用任何方法。
- RoleB可以调用方法Bar,但是不能调用构造函数。
因此,您的代码等同于:
[PrincipalPermission(SecurityAction.Demand, Role = "RoleA")]
class Foo
{
[PrincipalPermission(SecurityAction.Demand, Role = "RoleA")]
public Foo()
{
}
[PrincipalPermission(SecurityAction.Demand, Role = "RoleA")]
[PrincipalPermission(SecurityAction.Demand, Role = "RoleB")]
public static bool Bar()
{
return true;
}
}
如果您想使用 AND 组合需求,您应该将 Role= 指定为逗号分隔的列表,例如"RoleA,RoleB"。或者适当使用SecurityAction.Deny。
下面的例子说明了这一点:
class Program
{
static void Main(string[] args)
{
var aPrincipal = new GenericPrincipal(new GenericIdentity("AUser", ""), new[] {"RoleA"});
var bPrincipal = new GenericPrincipal(new GenericIdentity("BUser", ""), new[] { "RoleB" });
var abPrincipal = new GenericPrincipal(new GenericIdentity("ABUser", ""), new[] { "RoleB", "RoleA" });
// AB can do anything
Thread.CurrentPrincipal = abPrincipal;
var sc = new SecureClass();
TryConstruct();
TryBMethod(sc);
TryABMethod(sc);
// What can A do?
Thread.CurrentPrincipal = aPrincipal;
TryConstruct();
TryBMethod(sc);
TryABMethod(sc);
// What can B do?
Thread.CurrentPrincipal = bPrincipal;
TryConstruct();
TryBMethod(sc);
TryABMethod(sc);
Console.WriteLine("Press ENTER to exit");
Console.ReadLine();
}
static void TryConstruct()
{
try
{
var sc = new SecureClass();
}
catch(SecurityException)
{
Console.WriteLine("Constructor SecurityException for " + Thread.CurrentPrincipal.Identity.Name);
}
}
static void TryBMethod(SecureClass sc)
{
try
{
sc.RoleBMethod();
}
catch (SecurityException)
{
Console.WriteLine("RoleBMethod SecurityException for " + Thread.CurrentPrincipal.Identity.Name);
}
}
static void TryABMethod(SecureClass sc)
{
try
{
sc.RoleABMethod();
}
catch (SecurityException)
{
Console.WriteLine("RoleABMethod SecurityException for " + Thread.CurrentPrincipal.Identity.Name);
}
}
}
[PrincipalPermission(SecurityAction.Demand, Role ="RoleA")]
class SecureClass
{
public SecureClass()
{
Console.WriteLine("In constructor using " + Thread.CurrentPrincipal.Identity.Name);
}
[PrincipalPermission(SecurityAction.Demand, Role = "RoleB")]
public void RoleBMethod()
{
Console.WriteLine("In RoleBMethod using " + Thread.CurrentPrincipal.Identity.Name);
}
[PrincipalPermission(SecurityAction.Demand, Role = "RoleA,RoleB")]
public void RoleABMethod()
{
Console.WriteLine("In RoleBMethod using " + Thread.CurrentPrincipal.Identity.Name);
}
}
我的代码看起来像这样:
[PrincipalPermission(SecurityAction.Demand, Role = "RoleA")]
class Foo
{
[PrincipalPermission(SecurityAction.Demand, Role = "RoleB")]
public static bool Bar()
{
return true;
}
}
如果我尝试 运行 Foo.Bar();
如果我没有 RoleA,它将失败,但从不检查 RoleB。不管我有没有RoleB,只要有RoleA就可以。
如果我从 class 定义中删除 [PrincipalPermission(SecurityAction.Demand, Role = "RoleA")]
,那么它会按预期检查 RoleB。
我四处搜索,发现在两个不同的 SO 问题 (here and here) 中都提到了这个确切的问题,但在任何一种情况下都没有答案。有一条评论指向一个旧的 Microsoft Connect link,它应该包含答案,但没有评论或答案真正说明问题所在。
我真的非常感谢任何帮助。
多个 PrincipalPermissionAttribute 要求使用 OR 组合,因此在您的情况下:
- RoleA 可以构造 class 的实例并调用任何方法。
- RoleB可以调用方法Bar,但是不能调用构造函数。
因此,您的代码等同于:
[PrincipalPermission(SecurityAction.Demand, Role = "RoleA")]
class Foo
{
[PrincipalPermission(SecurityAction.Demand, Role = "RoleA")]
public Foo()
{
}
[PrincipalPermission(SecurityAction.Demand, Role = "RoleA")]
[PrincipalPermission(SecurityAction.Demand, Role = "RoleB")]
public static bool Bar()
{
return true;
}
}
如果您想使用 AND 组合需求,您应该将 Role= 指定为逗号分隔的列表,例如"RoleA,RoleB"。或者适当使用SecurityAction.Deny。
下面的例子说明了这一点:
class Program
{
static void Main(string[] args)
{
var aPrincipal = new GenericPrincipal(new GenericIdentity("AUser", ""), new[] {"RoleA"});
var bPrincipal = new GenericPrincipal(new GenericIdentity("BUser", ""), new[] { "RoleB" });
var abPrincipal = new GenericPrincipal(new GenericIdentity("ABUser", ""), new[] { "RoleB", "RoleA" });
// AB can do anything
Thread.CurrentPrincipal = abPrincipal;
var sc = new SecureClass();
TryConstruct();
TryBMethod(sc);
TryABMethod(sc);
// What can A do?
Thread.CurrentPrincipal = aPrincipal;
TryConstruct();
TryBMethod(sc);
TryABMethod(sc);
// What can B do?
Thread.CurrentPrincipal = bPrincipal;
TryConstruct();
TryBMethod(sc);
TryABMethod(sc);
Console.WriteLine("Press ENTER to exit");
Console.ReadLine();
}
static void TryConstruct()
{
try
{
var sc = new SecureClass();
}
catch(SecurityException)
{
Console.WriteLine("Constructor SecurityException for " + Thread.CurrentPrincipal.Identity.Name);
}
}
static void TryBMethod(SecureClass sc)
{
try
{
sc.RoleBMethod();
}
catch (SecurityException)
{
Console.WriteLine("RoleBMethod SecurityException for " + Thread.CurrentPrincipal.Identity.Name);
}
}
static void TryABMethod(SecureClass sc)
{
try
{
sc.RoleABMethod();
}
catch (SecurityException)
{
Console.WriteLine("RoleABMethod SecurityException for " + Thread.CurrentPrincipal.Identity.Name);
}
}
}
[PrincipalPermission(SecurityAction.Demand, Role ="RoleA")]
class SecureClass
{
public SecureClass()
{
Console.WriteLine("In constructor using " + Thread.CurrentPrincipal.Identity.Name);
}
[PrincipalPermission(SecurityAction.Demand, Role = "RoleB")]
public void RoleBMethod()
{
Console.WriteLine("In RoleBMethod using " + Thread.CurrentPrincipal.Identity.Name);
}
[PrincipalPermission(SecurityAction.Demand, Role = "RoleA,RoleB")]
public void RoleABMethod()
{
Console.WriteLine("In RoleBMethod using " + Thread.CurrentPrincipal.Identity.Name);
}
}