我已经搞砸了大约一天半,现在筛选.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 工作的方法?我一直在尝试制作自定义安全属性,但即使这样也行不通。我试图变得棘手并做:
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,这是以前可以使用的一个操作。然而,即使在这种情况下,CreatePermission() 方法仍然只在属性设置为 .Demand 时才被调用,而不是 .Deny!也许运行时实际上是检查属性而不是传递给 CodeAccessSecurityAttribute 构造函数的 SecurityAction?
我不确定这里还有什么可以尝试的……有人有什么想法吗?您不会认为基于角色拒绝方法访问会那么难,而不仅仅是要求它。让我感到非常不安的是,默认的 PrincipalPermission 从 IDE 中出现,就像执行 .Deny 一样很好,而且 MSDN 文档中有一个 1-liner 暗示它不起作用。如果指定了 .Demand 以外的任何其他内容,您会认为 PrincipalPermissionAttribute 构造函数会立即抛出异常,因为这可能会造成很大的安全漏洞!如果我没有进行单元测试,我永远不会意识到 .Deny 什么都不做!
同样,所有这一切都源于必须处理具有“只读”角色的现有安全模型,该角色需要被拒绝访问,而不是相反,我只授予对角色的访问权限。
谢谢你的帮助!
快速跟进:
我实际上可以通过这样做使我的自定义属性起作用:
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 做了一些有趣的事情,即使自定义构造函数覆盖它也是如此。