需求

可以声明方式或强制方式使用安全要求调用来指定直接或间接调用方访问您的库时必须拥有的权限。 直接调用方显式调用库的静态方法或实例方法,而间接调用方调用另一个库(该库调用您的库)的静态方法或实例方法。 当使用要求时,任何包含您的代码的应用程序只在所有直接和间接调用方均拥有该要求指定的权限时才执行。 当您的类库使用受保护的资源且您不想让不受信任的代码访问这些资源时,要求尤其有用。 可以使用强制性语法或声明式语法将要求放到代码中。

注意,.NET Framework 中的多数类已经有与它们关联的要求,所以任何时候在使用某个类访问受保护的资源时,不需要再发出额外的要求。 例如,StreamWriter 类每次打开时都自动发出对 FileIOPermission 的安全要求。 如果您在使用 StreamWriter 类时发出对 FileIOPermission 的要求,则会导致出现冗余且效率较低的堆栈步。 应当使用要求来保护需要自定义权限的自定义资源。

要求既可以是声明式的也可以是强制性的。

堆栈审核

要求通过执行一种分析(称为堆栈审核)来强制实施安全性,这种分析检查当前调用堆栈中的每一个调用函数(即堆栈帧)是否具有指定的权限。 当触发要求时,将发生下列情况。

  • 堆栈审核在调用方堆栈帧开始,而不是发生要求的当前堆栈。 例如,如何方法 A 调用方法 B,而方法 B 有一个要求,则堆栈审核在方法 A 的堆栈帧处开始。 方法 B 从不会被作为堆栈审核的一部分进行评估。

  • 堆栈审核贯穿调用堆栈持续进行,直至到达堆栈的程序入口点(通常为 Main 方法)或发现断言之类的堆栈审核修饰符。 有关堆栈审核修饰符的信息,请参见重写安全检查

  • 当需要相同权限的要求和堆栈审核修饰符(例如,断言)出现在同一堆栈帧时,要求优先。

  • 声明性和强制性语法在行为方面未体现出区别。

  • 注意,放置在程序入口点的要求从不会被评估,因为堆栈审核总是在调用堆栈帧开始,可是在这样的情况下,没有这样的调用帧可进行评估。 因此放置在程序入口点的要求总是会成功。

声明式要求

声明式要求使用特性将信息放入您代码的元数据。 可以使用声明式语法将要求放到代码的类级别或方法级别。

如果将声明式安全检查放到类级别,则它会应用到每个类成员。 但是,如果将声明式安全检查放到成员级别,则它只会应用到该成员,并重写在类级别指定的权限(如果存在)。 例如,假定您在类级别指定需要 PermissionA,并且对于该类的 Method1,指示需要 PermissionB。 在调用 Method1 时,安全检查将只查找 PermissionB,但该类的其他方法仍需要 PermissionA。

下面的示例向 ReadData 方法的所有调用方发出对 CustomPermission 自定义权限的声明式要求。 此权限是假设的自定义权限,在 .NET Framework 中并不存在。 该自定义权限有一个单独定义的 CustomPermissionAttribute 来发出该要求。 在此例中,它采用一个 SecurityAction.Demand 标志来指定该特性将执行的要求的类型。

<CustomPermissionAttribute(SecurityAction.Demand, Unrestricted := True)>Public Shared Function  ReadData() As String
   'Read from a custom resource.
End Function
[CustomPermissionAttribute(SecurityAction.Demand, Unrestricted = true)]
public static string ReadData()
{
   //Read from a custom resource.
}

强制性要求

通过创建权限对象的一个新实例并调用该对象的 Demand 方法,可将强制性要求放在代码的方法级别。 不能使用强制性语法将要求放在类级别。

如果在您的代码中放置强制性要求,则可有效地帮助保护在其中调用 Demand 方法的方法中剩余的所有代码。 执行 Demand 时会执行安全检查;如果安全检查失败,则会引发 SecurityException,并且除非捕获到 SecurityException 并加以处理,否则绝对不会执行该方法或成员中代码的其余部分。

下面的示例使用命令性语法向所有调用方发出对自定义权限 CustomPermission 的要求。 此代码创建 CustomPermission 类的一个新实例,将 PermissionState.Unrestricted 标志传递给构造函数。 然后调用 Demand 方法。

Public Shared Sub ReadData()
   Dim MyPermission As New CustomPermission(PermissionState.Unrestricted)
   MyPermission.Demand()
   'Read from a custom resource.
End Sub  
public static void ReadData()
{
   CustomPermission MyPermission = new CustomPermission(PermissionState.Unrestricted);
   MyPermission.Demand();

   //Read from a custom resource.
}
注意注意

要求操作的优化行为在 64 位和 32 位平台之间有所区别。在 64 位平台上,如果不存在其他调用程序集,要求不会检查包含该要求的程序集的授权集。但是,此优化不会引起特权提升,因为当调用程序集存在时,堆栈审核仍会执行。在 32 位平台上,要求操作检查包含该要求的程序集以及所有调用程序集的授权集。

请参见

参考

SecurityException

概念

利用特性扩展元数据

安全需求

代码访问安全性

创建自己的代码访问权限

添加声明式安全支持

编写安全类库