.NET声明性安全性:为什么SecurityAction.Deny无法使用?

时间:2009-07-07 14:54:38

标签: .net security declarative-security

我一直在弄乱这一天大约一天半,现在正在筛选.NET反射器和MSDN文档,并且无法解决任何问题......

在.NET框架中,您可以要求当前的Principal属于一个角色,以便能够通过标记这样的方法来执行方法:

[PrincipalPermission(SecurityAction.Demand, Role = "CanEdit")]
public void Save() { ... }

我正在使用已经定义了“ReadOnly”角色的现有安全模型,因此我需要完全相反的做法...如果用户处于“ReadOnly”角色,则阻止Save()方法。没问题,对吧?只需将SecurityAction翻转为.Deny:

[PrincipalPermission(SecurityAction.Deny, Role = "ReadOnly")]
public void Save() { ... }

嗯,事实证明这根本不起作用。该方法仍然运行良好。似乎PrincipalPermissionAttribute定义:

public override IPermission CreatePermission()

但是当属性设置为SecurityAction.Deny时,永远不会调用此方法,因此不会创建任何IPermission对象。有没有人知道如何获得.Deny工作?我一直试图制作一个自定义的secutiry属性,但即使这样也行不通。我试图变得棘手并且做:

public class MyPermissionAttribute : CodeAccessSecurityAttribute
{
    private SecurityAction securityAction;

    public MyPermissionAttribute(SecurityAction action)
        : base(SecurityAction.Demand)
    {
        if (action != SecurityAction.Demand && action != SecurityAction.Deny)
            throw new ArgumentException("Unsupported SecurityAction. Only Demand and Deny are supported.");
        this.securityAction = action;
    }

    public override IPermission CreatePermission()
    {
        // do something based on the SecurityAction...
    }
}

请注意,我的属性构造函数始终传递SecurityAction.Demand,这是之前可以使用的一个操作。 但是,即使在这种情况下,仍然只在属性设置为.Demand时调用CreatePermission()方法,而不是.Deny!也许运行时实际上是在检查属性而不是传递给CodeAccessSecurityAttribute构造函数的SecurityAction?

我不确定还有什么可以在这里尝试......任何人都有任何想法?您不会认为基于角色拒绝方法访问会很难,而不是仅仅要求它。真的让我感到不安的是,默认的PrincipalPermission出现在一个IDE中,就像在做一个.Deny就好了,并且在MSDN文档中有一个单线程,暗示它不起作用。如果指定了任何其他.Demand,您会认为PrincipalPermissionAttribute构造函数会立即抛出异常,因为这可能会造成很大的安全漏洞!我从来没有意识到这一点。如果我没有进行单元测试,Deny什么都不做!

同样,所有这些都源于必须处理具有“ReadOnly”角色的现有安全模型,该角色需要被拒绝访问,而不是以相反的方式执行,我只是授予对角色的访问权限。

感谢您的帮助!


快速跟进:

我实际上可以通过这样做来使我的自定义属性起作用:

public class MyPermissionAttribute : CodeAccessSecurityAttribute
{
    public SecurityAction SecurityAction { get; set; }

    public MyPermissionAttribute(SecurityAction action)
        : base(action)
    {
    }

    public override IPermission CreatePermission()
    {
        switch(this.SecurityAction) { ... } // check Demand or Deny
    }
}

装饰方法:

[MyPermission(SecurityAction.Demand, SecurityAction = SecurityAction.Deny, Role = "ReadOnly")]
public void Save() { ... }

但这非常难看,因为我在同一属性中指定了Demand和Deny。但它确实有用......

另一个有趣的说明:我的自定义类扩展了CodeAccessSecurityAttribute,而后者只扩展了SecurityAttribute。如果我使用我的自定义类来直接扩展SecurityAttribute,那么什么都行不通。因此,似乎运行时肯定只在元数据中查找CodeAccessSecurityAttribute实例,并使用指定的SecurityAction执行一些有趣的操作,即使自定义构造函数覆盖它也是如此。

0 个答案:

没有答案