如果应用于Class,则PrincipalPermission on Method不起作用

时间:2018-06-05 18:57:50

标签: c# .net principalpermission

我的代码看起来像这样:

[PrincipalPermission(SecurityAction.Demand, Role = "RoleA")]
class Foo
{
    [PrincipalPermission(SecurityAction.Demand, Role = "RoleB")]
    public static bool Bar()
    {
        return true;
    }
}

如果我尝试运行Foo.Bar();,如果我没有RoleA,则会失败,但从不检查RoleB。只要我有RoleA,它就可以工作,无论我是否有RoleB。

如果我从类定义中删除[PrincipalPermission(SecurityAction.Demand, Role = "RoleA")],那么它会按预期检查RoleB。

我已经四处搜索,发现在两个不同的SO问题(herehere)中提到的确切问题,两种情况都没有答案。一个评论指向一个旧的Microsoft Connect链接,该链接可能包含答案,但没有任何评论或答案实际上说明了问题所在。

我真的非常感谢任何帮助。

1 个答案:

答案 0 :(得分:0)

使用OR组合多个PrincipalPermissionAttribute命令,因此在您的情况下:

  • RoleA可以构造类的实例并调用任何方法。
  • 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组合Demands,则应将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);
    }

}