目录
CAS 概览
客户端 CAS
部分信任的客户端
客户端请求
原始 WCF 请求
PartialTrustClientBase<T> 的结构化请求
分析 Invoke 的请求
实现客户端结构化请求
在Microsoft .NET Framework 1.0 中引入的代码访问安全性 (CAS) 可 能是 .NET 与非托管代码相比唯一有所区别的功能。CAS 内置于 .NET Framework 的每个结构中,它影响托管代码中的每项操作,这些是非托管代码永 远无法做到的。
Windows Communication Foundation (WCF) 的第一个版本并不支持 CAS;System.ServiceModel 程序集不允许禁用了 CAS 支持的任何部分信任的调 用方。第二版在某些 HTTP 绑定中引入了对 CAS 的初步支持,但仅限于有限的 几种方案。这一更改使我能够着手编写小型框架,可以在不影响 WCF 编程模型 或 CAS 的情况下提供对 CAS 的全面支持。
在有关 CAS 的两个专栏的第一个中,我将简要讨论 WCF 中的代码访问安全 性,然后再介绍我的一个解决方案,它可以针对 WCF 服务启用部分信任的客户 端。
CAS 概览
.NET Framework 定义了 24 种不同的安全权限,它们几乎可以控制任何类型 的操作。这些权限包括文件 I/O、UI、反射、安全性、网络、数据访问等各个方 面。权限类型可以应用到特定的资源,例如文件 I/O 权限中的读取特定文件的 权限,或者 UI 权限中的显示特定类型窗口的权限。它也可以是完全拒绝(例如 拒绝执行任何文件 I/O 操作)或完全授予(例如不受限制的文件 I/O 访问)。
权限被分组为权限集,并为每个程序集都分配了一个。.NET Framework 定义 了一些标准权限集,例如 FullTrust(暗含所有权限)或 Execution(仅可访问 CPU 的权限)。管理员可以使用 .NET Configuration 工具定义自定义权限集, 而开发人员则可以通过编程方式来定义(或使用权限集文件,或使用应用程序所 需的权限集来定义)ClickOnce 应用程序清单。
加载程序集时,CLR 会为各个程序集分配其权限。程序集将提供某种形式的 身份证明以获得这些权限。其中包括检查程序集加载位置的基于来源的证明(例 如,所有来自全局程序集缓存 (GAC) 的代码都被授予完全信任权限),或者检 查程序集本身某些方面的基于内容的证明(例如,程序集的强名称)。
每个应用程序域始终都会被分配一个被称为应用程序域安全策略的权限集, 任何加载到该应用程序域的程序集都被限定为该权限集;否则将会出现安全异常 。新的应用程序域在开始时都具有 FullTrust 权限集,并且由于源自本地计算 机的所有代码默认都将获得 FullTrust 权限集,所以大多数基于 .NET 的应用 程序都以预设方式工作,与根本不使用 CAS 的效果完全一样。这使得代码(以 及用户、数据、计算机甚至网络)易于遭受各种形式的破坏,从病毒或蠕虫之类 的安全攻击到单纯的人为错误。
以低于完全信任级别运行的代码称为部分信任的代码。无论何时,托管代码 的任何片断试图使用 .NET Framework 访问资源或执行任何操作时(包括与非托 管代码之间的互操作),.NET Framework 都会验证包含该代码的程序集是否具 有执行该操作所需的权限。如果该程序集缺少所需的权限,.NET Framework 将 抛出安全异常,从而中止该操作。
由于受信任的程序集可能会被恶意的、不太受信任的程序集引诱执行某些不 太受信任的程序集没有权限执行的操作,所以仅对执行某项操作的程序集提出权 限要求尚嫌不够。因此,.NET Framework 会遍历整个调用方堆栈,确保堆栈中 的每个调用方都具有必要的权限。这种堆栈遍历被称为“安全要求” ,无论执行程序集的权限如何都必须满足此要求。
您的代码也可以声明权限——即,声明堆栈中的每个调用方都具 有所要求的权限。权限声明具有终止堆栈遍历的作用。您的代码只能声明它所具 有的权限,并且这还需要额外的特殊安全声明权限。
在声明一项权限的同时要求另一项就位是一种不错的想法。开发人员可以使 用专门的权限类或使用匹配的属性集通过编程方式要求或声明权限。开发人员也 可以在程序集、类或方法级别主动拒绝权限。拒绝权限或仅允许执行代码所需的 有限权限集可以减少受到引诱攻击的几率。有关代码访问安全性的更多信息,请 参阅我编写的《Programming .NET Components 2nd Edition》一书中的第 12 章,我在其中使用超过 100 页的篇幅介绍了这种基础方法及其应用。