首页 / 软件开发 / C# / Effective C#原则47:选择安全的代码
Effective C#原则47:选择安全的代码2010-12-13 博客园 Wu.Country@侠缘译.Net运行时已经设计好了,一些怀有恶意的代码不能渗透到远程计算机上并 执行。目前一些分部式系统依懒于从远程机器上下载和执行代码。如果你可以通 过Internet或者以太网来发布你的软件,或者直接从web上运行,但你须要明白 CRL在你的程序集中的一些限制。如果CLR不是完全相信一个程序集,它会限制一 些的行为。这些调用代码要有访问安全认证(CAS)。从另一方面来说,CLR强制要 求基于角色的安全认证,这样这些代码才能或者不能在基于一个特殊的角色帐号 下运行。安全违例是运行时条件,编译器不能强制它们。幸运的是,它 们绝不会在你的开发机器上出现,而且你所编译的代码从你自己的硬件上加载, 这就是说,它有更高的信任级别。讨论所有潜在的.Net安全模型可以足足写上几 本书,但你可以了解合理行为的一小部份,这样可以让你的程序集与.Net的安全 模式更容易的交互。这些推荐只有在你创建一个组件程序库时,或者是开发一些 通过网络发布的组件和程序集是才可以参考应用。通过这个讨论,你应 该记住.Net是一个托管的环境。这个环境保证有一个明确的安全环境。在安装时 可以用.Net的配置策略来管理安全策略。大多数.Net框架库是在安装时对配置策 略是安全信任的。它会查明安全问题,这就是说CLR可以检测IL而且确保它不会 有什么潜在的危险行为,例如直接访问原始内存。它不会在访问本地资源时要求 特殊的安全权限进行断言。你应该试着遵守同样的检测,如果你的代码不须要任 何的安全权限,就应该避免使用CAS的API来对断定访问权限,否则你所做的只是 降低程序性能。你要使用CAS的API来访问一些受保护的资源,而这些资 源是要求增加的特权的。很多通用的受保护资源是非托管的内存和文件系统。其 它一些受保护的资源还包括数据库,网络端口,windows注册表,以及打印子系 统。在每种情况下,如果调用代码没有足够的许可,试着访问这些资源都会引发 一个异常。而且,访问这些资源可能引发运行时建立一个安全栈上的询访,以确 保当前栈上的所有的程序集有恰当的许可。让我们看一下内存以及文件系统,讨 论安全系统和机密问题中最实际的一些问题。不管什么时候,你都可以 通过创建恰当的安全程序集来避免非托管内存访问。一个安全的程序集,也就是 一个不用使用任何指针来访问其它非托管,或者托管的堆内存。不管你是否知道 ,你所创建的所有C#代码几乎都是安全的。除非你在C#编译器上打开了不安全的 编译开关/unsafe,否则你所创建的都是安全代码(译注:就算打开了开关也不是 说就编译成不安全代码了,还要看你的代码是怎样写的。)。/unsafe充许用户使 用CLR不进行的验证的指针。要使用不安全代码的原因很少,特别是一常 规的任务中。指向原始内存的指针比要检测的安全的引用快一些。在一些经典的 数组中,它们可能要快上10倍以上。但当你使用不安全结构时,要明白任何的不 安全代码都会影响整个程序集。当你创建不安全块时,应该考虑把这些算法独立 到一个程序信中(参见原则32)。这样可以在整个程序上限制不安全代码的影响。 如果它是独立的,只有实际调用它的访问者才会受到影响。其它剩下的,你还是 可以在更严格的环境中使用安全机制。你可能还须要不安全代码来处理一些须要 直接指针的P/Invoke或者COM接口。同样的推荐:独立它。不安全代码只会影响 它自己的小程序集,不再有其它的。对于访问的建议很简单:只要可能 ,都应该避免访问非托管内存。接下来的安全核心就是文件系统。程序 要存储数据。从Internet上下载回来的代码,文件系统中的大多数地方都不能访 问,否则会有很大的安全漏洞。是的,完全不许访问文件系统就很难创建能使用 的程序。通过使用独立存储可以解决这一问题。独立存储可以穿越基于程序集而 独立的虚拟的目录,以及应用程序域,以及当前的用户。选择性的,你可以使用 更一般的独立存储虚拟目录,该目录是基于程序集或者当前用户的。实 际上,受信任的程序集可以访问他们自己特殊的独立存储区域,但不能是文件系 统的其它地方。独立的存储目录是隐藏在其它程序集以及其它用户中的。你可以 使用System.IO.IsolatedStorage名字空间中的类来访问独立的存储。 IsolatedStorageFile类包含的方法可以很简单的访问System.IO.File类。实际 上,它是从 System.IO. FileStream 类派生下来的。写内容到独立存储的代码 几乎与写内容到任何文件里是一样的:IsolatedStorageFile iso =
IsolatedStorageFile.GetUserStoreForDomain( );
IsolatedStorageFileStream myStream = new
IsolatedStorageFileStream( "SavedStuff.txt",
FileMode.Create, iso );
StreamWriter wr = new StreamWriter( myStream );
// several wr.Write statements elided
wr.Close ();