Demand 和 LinkDemand
更新:2007 年 11 月
声明式安全提供了两种安全检查,它们很类似,但却执行完全不同的检查。这两种形式的安全检查您都应当了解,因为如果选择不当,则会削弱安全性或降低性能。有关更多信息,请参见安全性要求。
声明式安全提供了下面的安全检查:
Demand 指定代码访问安全性堆栈审核。堆栈上的所有调用方必须传递指定的权限或标识。Demand 出现在每一个调用中,因为堆栈可能包含不同的调用方。如果您重复调用某一方法,则每次都会进行这种安全检查。Demand 可以很好地防范诱惑性攻击;未经授权的代码在尝试通过这种检查时会被捕获。
LinkDemand 在实时 (JIT) 编译时发生,只检查直接调用方。这种安全检查不检查调用方的调用方。一旦通过该检查,则无论调用方调用多少次,都不会有进一步的安全性系统开销。然而,对于诱惑性攻击,它无法起保护作用。使用 LinkDemand 时,任何通过了测试并且可以引用您的代码的代码,都可能会因为允许恶意代码利用已授权的代码进行调用而破坏安全性。因此,除非已经完全避免了所有可能的弱点,否则,请不要使用 LinkDemand。
对于使用 LinkDemand 时所需的额外防范措施,必须单独进行编程;安全系统可以帮助实施这些措施。任何错误都会暴露安全弱点。所有已授权的使用您的代码的代码都必须负责实现进一步的安全性,方法是执行下列操作:
限制调用代码对类或程序集的访问。
对被调用代码和调用代码执行同样的安全检查,并强制调用方这样做。例如,如果您编写的代码调用一个方法,而该方法受一个要求 SecurityPermission 的 LinkDemand(已指定 UnmanagedCode 标志)保护,则您的方法也必须使用要求此权限的 LinkDemand(或安全性更强的 Demand)。一种例外情况是:在您的代码中已有其他安全保护机制(例如要求)的前提下,您的代码以一种您认为是安全的、受限制的方式使用由 LinkDemand 保护的方法。在这种例外情况下,调用方对削弱基础代码的安全保护负责。
确保代码的调用方无法以欺骗手段使您的代码为它们调用受保护的代码。换句话说,调用方不能强制被授权的代码向受保护的代码传递特定参数,或从受保护的代码中得到返回结果。
接口和链接要求
如果一个具有 LinkDemand 的虚方法、属性或事件重写基类方法,则基类方法也必须对被重写的方法使用了同样的 LinkDemand 才能有效。恶意代码有可能会重新强制转换为基类型,并调用基类方法。另请注意,链接要求可以隐式地添加到不具备 AllowPartiallyTrustedCallersAttribute 程序集级属性的程序集中。
当接口方法也有链接要求时,使用链接要求来保护方法实现是一个很好的做法。请注意下面的有关对接口使用链接要求的说明:
AllowPartiallyTrustedCallersAttribute 属性也适用于接口。
可以将链接要求用于接口,以便有选择地保护某些接口,防止部分受信任的代码使用它们,例如,在使用 AllowPartiallyTrustedCallersAttribute 属性时。
如果程序集中定义的接口不包含 AllowPartiallyTrustedCallersAttribute 属性,您可以在部分受信任的类上实现该接口。
如果您对一个类的公共方法使用 LinkDemand,该类实现一个接口方法,则在您强制转换到该接口并调用该方法时,不会执行 LinkDemand。在这种情况下,由于您链接到该接口,因此只有该接口上的 LinkDemand 才有效。
检查下列与安全问题相关的项:
接口方法上的显式链接要求。确保这些链接要求可以提供预期的保护。确定恶意代码是否能够像上面所说的那样使用强制转换来绕过这些链接要求。
应用了链接要求的虚方法。
它们实现的类型和接口。这些类型和接口应该一致使用链接要求。