设计权限

权限表示访问受保护资源或执行受保护操作的能力。 当实现自己的权限类时,您必须作出一些高级别的设计决定。 开始的步骤中有一步是确定究竟计划让您的自定义权限保护什么资源。

下一步要确定是否存在任何有关重叠权限的问题。 虽然希望避免让两个权限保护同一资源,但在某些情况下,您无法合理地予以避免。 例如,访问非托管代码的权限还可包括其他权限,因为被授予访问非托管代码的权限的代码几乎可通过非托管 API 执行任何操作。 但是,在未授予访问非托管代码的权限时,您仍需要授予访问其他特定资源的权限。 因此,将访问非托管代码的权限与其他权限分开是有意义的。

如何知道权限范围的重叠是否为可管理的? 没有绝对答案,但有一点需要考虑:是不是其中的一个权限表示的访问权比另一个权限表示的访问权更细微,从而授予前者通常比授予后者更容易。 如果是这种情况,则在许多情况下授予访问权限很容易,从而使管理员的任务比较容易完成。

决定您的权限将保护哪些资源并解决了有关权限重叠的任何问题后,您必须决定访问控制的细微程度。 此问题的答案将影响您设计表示权限状态的变量的方式,并确定管理员是否能够配置对受保护资源的访问权。 它还会影响性能、使用是否方便以及其他因素。

为了阐释这些设计问题中的一部分问题,请考虑可能已经为 FileIOPermission 类选择的、.NET Framework 提供的一些设计。 每种设计选择都会影响表示权限状态的变量。

  • 一位,含义为“使用所有文件”或“不使用文件”,具体是哪种含义取决于其值。

  • 两位,含义为“读取所有文件”和“写入所有文件”或相反,具体取决于这两位的值。

  • 26 位,含义为“使用指定驱动器上的所有文件”。

  • 一个字符串数组,列出了被授予访问权的所有文件。

显然,需要考虑多种平衡因素。 例如,一位权限非常简单、快捷而又易于理解,但它为管理员提供一种或者全用或者全部不用的选择,这种选择可能不理想。 指定较复杂的权限状态表示形式的其他选择可能会在某种程度上降低性能。 您必须掂量这些平衡因素,并考虑不应创建多个权限来保护同一资源。 一般情况下,在设计权限类时,应当按需要确定权限状态的复杂程度,从而不会对性能造成很大影响。

尽管其他设计也是可能的,但多数权限遵循下列标准设计模式之一或这些模式的组合:

  • 布尔型权限。 这种最简单的权限对象类型包含一位或多位,每位分别对应于“执行 X 操作需要的权限”。 您或者拥有权限,或者没有权限。 SecurityPermission 类是这种类型权限的一个示例,其状态包含一些布尔型变量,这些变量表示执行不同操作的权限(如调用非托管代码的权限),每一权限或者被允许,或者不被允许。

  • 权限的级别。 这种更详细形式的权限拥有多个变量,这些变量将每种访问权表示为一个数字,该数字介于零(表示根本没有访问权限)和某个较大的数字(表示完全无限制的访问权限)之间,两个数字之间有若干级别。 例如,您可以使用 UIPermission 类来表示使用窗口时需要的不同级别的权限,从没有 UI 权限到无限制 UI 权限,二者之间存在若干不同的级别。

  • 对象列表权限。 这种类型的权限对允许什么或不允许什么提供了非常详细的规范。 FileIOPermission 类是此类型权限的一个很好的示例,因为其状态是由一些文件列表表示的(允许对这些文件进行某些类型的访问)。 带有列表的权限对保护包含大量命名对象的资源最有用。

一般情况下,最好尽量减少自定义权限类中的外部依赖项,因为在安全系统需要使用您的权限类时,必须加载您的权限所依赖的每个程序集。 如果可能,应当将您的自定义权限和与其关联的任何特性类放到它自己的单独程序集内,以减少不必要地加载其他程序集的可能性。

请参见

概念

创建自己的代码访问权限

代码访问安全性