我正在我的.net 4.5应用程序中实现基于声明的安全性。很多箍要跳过,但它基本上都在工作。
我不喜欢的唯一部分是我无法创建自己的属性。 ClaimsPrincipalPermissionAttribute已被密封。为什么呢?
我总是在我的应用程序中标记,例如:
[ClaimsPrincipalPermission(SecurityAction.Demand, Resource = "Foo", Operation = "Bar")]
因为我希望我的资源和操作字符串不会拼写错误并且易于重构,所以我创建了类,所以我可以这样做:
[ClaimsPrincipalPermission(SecurityAction.Demand, Resource = Resources.Foo, Operation = Operations.Foo.Bar)]
(请注意,由于不同的资源可能具有不同的操作,因此操作本身由资源子类化。)
这一切都很好,花花公子,但每次输入或复制/粘贴都是一个很大的问题。我宁愿做类似的事情:
[DemandPermission(Resources.Foo, Operations.Foo.Bar)]
我可以创建这个属性,但我需要从ClaimsPrincipalPermissionAttribute继承,我不能,因为它是密封的。 :(
还有其他方法可以解决这个问题吗?也许我不需要继承,但是我可以以某种方式注册我自己的属性类型,所以它可以在所有相同的地方工作吗?
答案 0 :(得分:7)
ClaimsPrincipalPermissionAttribute
来自CodeAccessSecurityAttribute
。除了实现CreatePermission()
基于您传入的资源和操作的值返回新的ClaimsPrincipalPermission
之外,它几乎没有任何作用。
你可以实现一个派生自CodeAccessSecurityAttribute
的新类(这不是密封的)来做你想做的事。
使用JustDecompile,您可以看到ClaimsPrincipalPermissionAttribute
中的代码很简单。您可以像这样创建自己的属性:
[AttributeUsage(AttributeTargets.Class | AttributeTargets.Method | AttributeTargets.Property, AllowMultiple = true)]
public sealed class DemandPermissionAttribute : CodeAccessSecurityAttribute
{
public Operations Operation { get; set; }
public Resources Resource { get; set; }
public DemandPermissionAttribute(SecurityAction action = SecurityAction.Demand)
: base(action)
{
}
public override IPermission CreatePermission()
{
return new ClaimsPrincipalPermission(this.Resource.ToString(), this.Operation.ToString());
}
}
需要注意的一件重要事情是,您必须在引用它的单独程序集中定义自定义属性,否则框架将抛出TypeLoadException
,如此处所述
http://msdn.microsoft.com/en-us/library/vstudio/yaah0wb2.aspx
另外,请注意构造函数参数的默认值的使用。您需要有一个构造函数,该构造函数为该属性提供SecurityAction
参数,以便由框架实例化。在这种情况下,DemandPermission
可能是个坏名称,因为您可以将SecurityAction
覆盖为SecurityAction.Demand
以外的其他内容。
答案 1 :(得分:3)
ClaimsPrincipalPermissionAttribute已被密封。为什么呢?
Eric Lippert谈到了封装在Framework类型中的共性,因为我们讨论代码安全性,所以这一点非常重要:
每次实现一个采用未密封类型实例的方法时,您必须编写该方法,以便在面对该类型的潜在恶意实例时保持健壮。你不能依赖任何你知道对你的实现都是真实的不变量,因为一些敌对的网页可能是你的实现的子类,覆盖虚拟方法来做弄乱你的逻辑的东西,然后传入它。每次我密封一个类,我可以编写使用该类的方法,并确信我知道该类的功能。
在这种情况下,这更为重要,ClaimsPrincipalPermissionAttribute
通过IClaimsPrincipal
接口进行检查。因此,通过使ClaimsPrincipalPermissionAttribute
密封,它们允许IClaimsPrincipal
的任何实现者不必担心恶意实现。这是相当节省的,因为这与所有安全相关。
答案 2 :(得分:1)
我的直接反应是,写作并不是很多 - 你需要多久写一次?如果控制器中的操作是通用的,则将其放在控制器上 - 如果适用于许多控制器,则创建具有该属性的ControllerBase。
如果您的案例比这更特殊,我想您将被迫实施各种属性。