安全透明的代码,级别 2

.NET Framework 4 版中引入了 2 级透明度。 此模型的三个原则是透明代码、安全可靠关键代码和安全关键代码。

  • 透明代码(包括作为完全信任的代码运行的代码)可以仅调用其他透明代码或安全可靠关键代码。 它只能执行域的部分信任权限集(如果存在)所允许的操作。 透明代码不能执行以下操作:

    此外,透明方法不能重写关键虚方法,也不能实现关键接口方法。

  • 安全关键代码是完全受信任的,但可由透明代码调用。 它将公开完全信任代码的有限外围应用;正确性和安全验证将在安全关键代码中进行。

  • 安全关键代码是完全受信任的,它可以调用任何代码,但透明代码无法调用它。

本主题包含以下各节:

  • 用法示例和行为

  • 重写模式

  • 继承规则

  • 其他信息和规则

用法示例和行为

若要指定 .NET Framework 4 规则(2 级透明度),请对程序集使用下面的批注:

[assembly: SecurityRules(SecurityRuleSet.Level2)]

若要应用 .NET Framework 2.0 规则(1 级透明度),请使用下面的批注:

[assembly: SecurityRules(SecurityRuleSet.Level1)]

如果没有对程序集进行批注,则默认情况下将使用 .NET Framework 4 规则。 但是,建议的最佳做法是使用 SecurityRulesAttribute 特性,而不是依赖于默认值。

程序集范围的批注

下列规则适用于程序集级别的特性使用:

  • 无特性:如果没有指定任何特性,则运行时会将所有代码解释为安全关键代码,除非这些代码成为安全关键的代码会违反继承规则(例如,在重写或实现透明虚方法或接口方法时)。 在上述情况下,这些方法是安全关键方法。 不指定任何特性会导致公共语言运行时为您确定透明度规则。

  • SecurityTransparent:所有代码都是透明的;整个程序集将不会执行任何具有特权的或不安全的操作。

  • SecurityCritical:程序集中的类型所引入的所有代码都是关键代码;所有其他代码都是透明代码。 此方案与没有指定任何特性的方案类似;但是公共语言运行时不会自动确定透明度规则。 例如,如果重写虚方法或抽象方法或者实现接口方法,则默认情况下该方法是透明的。 必须将该方法显式批注为 SecurityCritical 或 SecuritySafeCritical;否则,加载时将引发 TypeLoadException。 当基类和派生类都位于同一程序集中时,此规则也适用。

  • AllowPartiallyTrustedCallers(仅 2 级):所有代码都默认是透明的。 但是,各个类型和成员可有其他特性。

下表将级别 2 的程序集级别行为与级别 1 的程序集级别行为进行了比较。

程序集特性

级别 2

级别 1

部分信任的程序集上无特性

虽然类型和成员都默认是透明的,但它们可以是安全关键的或安全可靠关键的。

所有类型和成员都是透明的。

无特性

不指定任何特性会导致公共语言运行时为您确定透明度规则。 所有类型和成员都是安全关键的,除非它们成为安全关键的会违反继承规则。

在完全信任的程序集(位于全局程序集缓存中或在 AppDomain 中标识为完全信任)上,所有类型都是透明的,并且所有成员都是安全可靠关键的。

SecurityTransparent

所有类型和成员都是透明的。

所有类型和成员都是透明的。

SecurityCritical(SecurityCriticalScope.Everything)

不适用。

所有类型和成员都是安全关键的。

SecurityCritical

此程序集中的类型所引入的所有代码都是关键代码;所有其他代码都是透明代码。 如果重写虚方法或抽象方法或者实现接口方法,则必须将此方法显式批注为 SecurityCritical 或 SecuritySafeCritical。

所有代码都默认是透明的。 但是,各个类型和成员可有其他特性。

类型和成员批注

适用于某个类型的安全特性也适用于该类型所引入的成员。 但是,它们不适用于对基类或接口实现的虚拟或抽象重写。 下列规则适用于类型和成员级别的特性使用:

  • SecurityCritical:类型或成员是关键的,并且只能由完全信任代码调用。 安全关键类型中引入的方法是关键的。

    重要说明重要事项

    基类或接口中引入的并在安全关键类中重写或实现的虚方法或抽象方法都默认是透明的。必须将它们标识为 SecuritySafeCritical 或 SecurityCritical。

  • SecuritySafeCritical:类型或成员是安全关键的。 但是,可以从透明的(部分信任的)代码调用类型或成员,它们具有与任何其他关键代码一样的功能。 必须对代码进行审核以确保安全。

返回页首

重写模式

下表显示 2 级透明度允许的方法重写。

基虚拟/接口成员

重写/接口

Transparent

Transparent

Transparent

SafeCritical

SafeCritical

Transparent

SafeCritical

SafeCritical

Critical

Critical

返回页首

继承规则

在此节中,将根据访问和功能为 Transparent、Critical 和 SafeCritical 代码分配下列顺序:

Transparent < SafeCritical < Critical

  • 针对类型的规则:访问权限从左到右受到的限制性越来越大。 派生类型必须至少具有与基类型一样的限制。

  • 针对方法的规则:派生方法不能从基方法更改可访问性。 对于默认行为,所有未进行批注的派生方法都为 Transparent。 如果未将重写方法显式批注为 SecurityCritical,则关键类型的派生对象会导致引发异常。

下表显示允许的类型继承模式。

基类

派生类可以是

Transparent

Transparent

Transparent

SafeCritical

Transparent

Critical

SafeCritical

SafeCritical

SafeCritical

Critical

Critical

Critical

下表显示禁止的类型继承模式。

基类

派生类不能是

SafeCritical

Transparent

Critical

Transparent

Critical

SafeCritical

下表显示允许的方法继承模式。

基方法

派生方法可以是

Transparent

Transparent

Transparent

SafeCritical

SafeCritical

Transparent

SafeCritical

SafeCritical

Critical

Critical

下表显示禁止的方法继承模式。

基方法

派生方法不能是

Transparent

Critical

SafeCritical

Critical

Critical

Transparent

Critical

SafeCritical

注意注意

这些继承规则适用于级别 2 的类型和成员。级别 1 的程序集中的类型可以继承自级别 2 的安全关键类型和成员。因此,级别 2 的类型和成员必须具有针对级别 1 的继承者的单独继承要求。

返回页首

其他信息和规则

LinkDemand 支持

2 级透明度模型将 LinkDemand 替换为 SecurityCriticalAttribute 特性。 在旧的(级别 1)代码中,LinkDemand 自动被视为 Demand

反射

调用关键方法或读取关键字段将触发对完全信任的要求(就像您正在调用私有方法或字段一样)。 因此,完全信任代码可以调用关键方法,而部分信任代码则不能这样做。

已将下面的属性添加到 System.Reflection 命名空间,从而确定类型、方法或字段是 SecurityCritical、SecuritySafeCritical 还是 SecurityTransparent:IsSecurityCriticalIsSecuritySafeCriticalIsSecurityTransparent。 通过使用这些属性,可以利用反射而不是检查特性是否存在来确定透明度。 透明度规则是复杂的,检查特性可能还不够。

注意注意

SafeCritical 方法为 IsSecurityCriticalIsSecuritySafeCritical 返回 true,因为 SafeCritical 确实是关键的(它具有与关键代码相同的功能,但可以从透明代码调用它)。

动态方法继承它们所附加到的模块的透明度;它们不继承类型的透明度(如果将它们附加到类型)。

跳过完全信任中的验证

可以通过在 SecurityRulesAttribute 特性中将 SkipVerificationInFullTrust 属性设置为 true,跳过对完全信任的透明程序集的验证。

[assembly: SecurityRules(SecurityRulesSet.Level2, SkipVerificationInFullTrust = true)]

默认情况下,SkipVerificationInFullTrust 属性为 false,因此必须将该属性设置为 true 才能跳过验证。 应仅出于优化目的执行此操作。 应使用 PEVerify 工具中的 transparent 选项来确保程序集中的透明代码是可验证的。

返回页首

请参见

概念

安全透明的代码,级别 1

.NET Framework 4 中的安全性更改