本文介绍在部分信任环境中运行 Windows Communication Foundation (WCF)时的最佳做法。
序列化
在部分受信任的应用程序中使用 DataContractSerializer 时应用这些做法。
所有可序列化类型都必须使用特性显式标记 [DataContract]
。 部分信任环境中不支持以下技术:
- 使用 SerializableAttribute 标记要序列化的类。
- 实现 ISerializable 接口以允许类控制其序列化过程。
使用 DataContractSerializer
使用
[DataContract]
特性标记的所有类型都必须是公共的。 无法在部分信任环境中序列化非公共类型。可序列化
[DataContract]
类型中的所有[DataContract]
成员都必须是公共的。 在部分信任环境中,具有非公共[DataMember]
的类型无法进行序列化。处理序列化事件的方法(例如
OnSerializing
,OnSerialized
和OnDeserializing
OnDeserialized
)必须声明为公共事件。 但是,同时支持 OnDeserialization(Object) 的显式实现和隐式实现。[DataContract]
在标记的 AllowPartiallyTrustedCallersAttribute 程序集中实现的类型不得在类型构造函数中执行与安全相关的操作,因为 DataContractSerializer 反序列化期间不调用新实例化对象的构造函数。 具体说来,对于[DataContract]
类型,必须避免使用以下常见安全技术:通过将类型的构造函数设为内部或私有来尝试限制部分信任访问。
通过向类型的构造函数添加一个
[LinkDemand]
来限制对该类型的访问。假设由于对象已成功实例化,构造函数强制实施的任何验证检查都已成功通过。
使用 IXmlSerializable
下面的最佳实践适用于实现IXmlSerializable并使用DataContractSerializer进行序列化的类型。
GetSchema静态方法实现必须是
public
。实现接口的 IXmlSerializable 实例方法必须是
public
。
在允许部分受信任调用方进行调用的完全受信任平台代码中使用 WCF
WCF 部分信任安全模型假定 WCF 公共方法或属性的任何调用方在宿主应用程序的代码访问安全性 (CAS) 上下文中运行。 WCF 还假定每个 AppDomain应用程序都只存在一个应用程序安全上下文,并且此上下文是在 AppDomain 创建时由受信任的主机(例如,由调用 CreateDomain 或 ASP.NET 应用程序管理器建立)。
注释
代码访问安全性(CAS)已在 .NET Framework 和 .NET 的所有版本中弃用。 使用与 CAS 相关的 API 时,最新版本的 .NET 不遵循 CAS 注释并生成错误。 开发人员应寻求完成安全任务的替代方法。
此安全模型适用于无法断言其他 CAS 权限的用户编写应用程序,例如在中等信任 ASP.NET 应用程序中运行的用户代码。 但是,完全受信任的平台代码(例如,安装在全局程序集缓存中并接受来自部分受信任代码的调用的第三方程序集)在代表部分受信任的应用程序调用 WCF 时必须小心谨慎,以避免引入应用程序级安全漏洞。
完全信任代码应避免在代表部分受信任代码调用 WCF API 之前,更改当前线程的 CAS 权限集(通过调用Assert、PermitOnly或Deny)。 断言、拒绝或其他方式创建独立于应用程序级安全上下文的线程特定权限上下文可能会导致意外行为。 根据应用程序的不同,此行为可能会导致应用程序级安全漏洞。
使用特定于线程的权限上下文调用 WCF 的代码必须准备好处理可能出现的以下情况:
在作期间,可能无法维护特定于线程的安全上下文,这会导致潜在的安全异常。
内部 WCF 代码和任何用户提供的回调可以在不同于最初启动调用的安全上下文中运行。 这些上下文包括:
应用程序权限上下文。
其他用户线程以前创建的任何线程特定的权限上下文,用于在当前正在运行的 AppDomain 的生存期内调用到 WCF。
WCF 保证部分受信任的代码无法获取完全信任权限,除非在调用 WCF 公共 API 之前由完全受信任的组件断言此类权限。 但是,它不保证断言完全信任的效果隔离到特定的线程、操作或用户操作。
最佳做法是,避免通过调用Assert或PermitOnlyDeny创建特定于线程的权限上下文。 相反,授予或拒绝应用程序本身的权限,因此不需要 Assert、Deny 或 PermitOnly。