Effective C#之Item 47:Prefer Safe Code

  rel="File-List" href="file:///C:%5CDOCUME%7E1%5CHelios%5CLOCALS%7E1%5CTemp%5Cmsohtmlclip1%5C01%5Cclip_filelist.xml"> rel="themeData" href="file:///C:%5CDOCUME%7E1%5CHelios%5CLOCALS%7E1%5CTemp%5Cmsohtmlclip1%5C01%5Cclip_themedata.thmx"> rel="colorSchemeMapping" href="file:///C:%5CDOCUME%7E1%5CHelios%5CLOCALS%7E1%5CTemp%5Cmsohtmlclip1%5C01%5Cclip_colorschememapping.xml">

Item 47: Prefer Safe Code

选择安全代码

The .NET runtime has been designed so that malicious code cannot infiltrate and execute on a remote machine. Yet some distributed systems rely on downloading and executing code from remote machines. If you might be delivering your software via the Internet or an intranet, or running it directly from the web, you need to understand the restrictions that the CLR will place on your assemblies. If the CLR does not fully trust an assembly, it limits the allowed actions. This is called code access security (CAS). On another axis, the CLR enforces role-based security, in which code might or might not execute based on a particular user account's privileges.

.NET运行时设计成这样:恶意代码不能渗透并在远程机器上执行。然而一些分布式系统依赖于从远程机器下载和执行代码。如果你要通过互联网或者局域网来传递系统的话,或者直接从web上运行,那么你就需要理解CLR在你的程序集上的限制。如果CLR不完全信任程序集,就会限制允许的动作。这叫做代码访问安全(CAS)。从另一方面来讲,CLR强制基于角色的安全,即,代码能不能被执行,基于特定的用户账号权限。

Security violations are runtime conditions; the compiler cannot enforce them. Furthermore, they are far less likely to show up on your development machine; code that you compile is loaded from your hard drive and, therefore, has a higher trust level. Discussing all the implications of the .NET Security model fills volumes, but you can take a small set of reasonable actions to enable your assemblies to interact with the .NET security model more easily. These recommendations apply only if you are creating library components, or components and programs that might be delivered across the web.

违反安全是运行时的条件;编译器不能强制它们。进一步说,在你的开发微机上,它们不大可能会表现出来;你编译的代码从你的硬盘加载,因此,有较高的信任级别。讨论所有相关的.NET安全模型实现得要几卷书,但是你可以采取一小部分合理的动作,使你的程序集更容易的和.Net安全模型进行交互。只有当你正在创建库组件或者会通过web传输的组件和程序时,这些建议才合适。

Throughout this discussion, remember that .NET is a managed environment. The environment guarantees a certain amount of safety. The bulk of the .NET Framework library is granted full trust through the .NET config policy when it is installed. It is verifiably safe, which means that the CLR can examine the IL and ensure that it does not perform any potentially dangerous actions, such as accessing raw memory. It does not assert any particular security rights needed to access local resources. You should try to follow that same example. If your code does not need any particular security rights, avoid using any of the CAS APIs to determine your access rights; all you do is decrease performance.

通过这些讨论,记住.NET是一个托管的环境。该环境保障了一定程度的安全性。当安装.NET环境时,通过.NET的配置策略,可以完全信任整个.NET框架库。它是确定安全的,这意味着CLR可以检查IL代码,保证它不会执行任何潜在的危险代码,例如访问原始内存。对于访问本地资源,它不声明任何特殊安全权限。你应该努力遵守同样的规则。如果你的代码不需要任何特定的安全权限,那么就避免使用任何CAS API来决定访问权限;你做的所有工作都会降低性能。

You will use the CAS APIs to access a small set of protected resources that demand increased privileges. The most common protected resources are unmanaged memory and the file system. Other protected resources include databases, network ports, the Windows Registry, and the printing subsystem. In each case, attempting to access those resources fires exceptions when the calling code does not have the proper permissions. Furthermore, accessing those resources might cause the runtime to perform a security stack walk to ensure that all assemblies in the current call stack have the proper permissions. Let's look at memory and the file system, discussing the best practices for a secure and safe program.

你将会使用CAS API来访问一些要求提升权限的受保护的资源。最常见的受保护资源就是未托管内存和文件系统。其它受保护的资源包括数据库,网络端口,Windows注册表和打印子系统。对于每种情况,尝试访问这些资源时,一旦调用代码没有获得合适的许可,就会引发异常。进一步说,访问这些资源可能会引起运行时对安全栈进行遍历,以此来保证当前的调用栈里面的所有程序集都有合适的许可。让我们来看内存和文件系统,讨论一个安全的系统里面最好的实践。

You can avoid unmanaged memory access by creating verifiably safe assemblies whenever possible. A safe assembly is one that does not use any pointers to access either the managed or unmanaged heaps. Whether you knew it or not, almost all the C# code that you create is safe. Unless you turn on the /unsafe C# compiler option, you've created verifiably safe code. /unsafe allows the user of pointers, which the CLR cannot verify.

只要可能,就创建验证性的安全程序集,你可以避免未托管内存访问。安全的程序集不使用任何指针访问托管的或者未托管的堆。不管你知不知道,几乎你创建的所有C#代码都是安全的。除非你打开C#编译器的/unsafe选项。你已经创建了验证安全的代码。/unsafe允许用户指针,这是CLR不能验证的。

The reasons to use unsafe code are few, with the most common being performance. Pointers to raw memory are faster than safe reference checks. In a typical array, they can be up to 10 times faster. But when you use unsafe constructs, understand that unsafe code anywhere in an assembly affects the entire assembly. When you create unsafe code blocks, consider isolating those algorithms in their own assembly (see Item 32). This limits the affect that unsafe code has on your entire application. If it's isolated, only callers who need the particular feature are affected. You can still use the remaining safe functionality in more restrictive environments. You might also need unsafe code to deal with P/Invoke or COM interfaces that require raw pointers. The same recommendation applies: Isolate it. Unsafe code should affect its own small assembly and nothing else.

使用非安全代码的理由很少,其中最常见的就是性能。指向原始内存的指针比安全的引用检查要快。在一个典型的数组中,能够快到10倍。但是当你使用非安全的结构体时,要理解程序集里面各处的非安全代码会影响整个程序集。当你创建非安全代码块时,考虑将这些算法隔离在它们自己的程序集里面(Item32)。这就限制了非安全代码整个应用程序的影响。如果它被隔离了,只有需要该特殊特性的调用者才会受影响,你仍然可以在更严格的环境下使用其余的安全功能。你可能也需要非安全代码来处理需要原始指针的P/Invoke或者COM接口。同样的建议也适用:隔离它。非安全代码应该只影响它自己的小程序集,不能影响其余的。

The advice for memory access is simple: Avoid accessing unmanaged memory whenever possible.

对于内存访问的建议很简单:任何时候只要可能就避免访问未托管内存。

The next most common security concern is the file system. Programs store data, often in files. Code that has been downloaded from the Internet does not have access to most locations on the file system that would be a huge security hole. Yet, not accessing the file system at all would make it far more difficult to create usable programs. This problem is solved by using isolated storage. Isolated storage can be thought of as a virtual directory that is isolated based on the assembly, the application domain, and the current user. Optionally, you can use a more general isolated storage virtual directory that is based on the assembly and the current user.

下一个最常见的安全问题是文件系统。程序要存储数据,经常是存在文件里面。从互联网上下载来的代码,不应该对文件系统的多数位置有访问权,否则,那将是巨大的安全漏洞。然而,根本不允许访问文件系统的话,会使得创建可用的程序很困难。使用隔离存储可以解决该问题。隔离存储可以被认为是:基于程序集、应用程序域和当前用户的,进行隔离的虚拟目录。更随意点,你可以使用一般的隔离存储目录,它基于程序集和当前用户。

Partially trusted assemblies can access their own specific isolated storage area, but nowhere else on the file system. The isolated storage directory is hidden from other assemblies and other users. You use isolated storage through the classes in the System.IO.IsolatedStorage namespace. The IsolatedStorageFile class contains methods very similar to the System.IO.File class. In fact, it is derived from the System.IO. FileStream class. The code to write to isolated storage is almost the same as writing to any file:

部分受信任的程序集可以访问它们特定的隔离存储区域,但不能访问文件系统的其它地方。隔离存储目录对于其它程序集和用户来说是不可见的。通过使用System.IO.IsolatedStorage命名空间下面的类来隔离存储。IsolatedStorageFile类包含与System.IO.File类相似的方法。事实上,它是从System.IO. FileStream类派生的。向隔离存储进行写入的代码几乎和向任何文件进行写入的代码一样:

  1. IsolatedStorageFile iso = IsolatedStorageFile.GetUserStoreForDomain( );
  2.  
  3. IsolatedStorageFileStream myStream = new IsolatedStorageFileStream( "SavedStuff.txt", FileMode.Create, iso );
  4. StreamWriter wr = new StreamWriter( myStream );
  5. // several wr.Write statements elided
  6. wr.Close();
  7.  
  8. //Reading is equally familiar to anyone who has used file I/O:
  9. IsolatedStorageFile isoStore = IsolatedStorageFile.GetUserStoreForDomain( );
  10.  
  11. string[] files = isoStore.GetFileNames( "SavedStuff.txt" );
  12. if ( files.Length > 0 )
  13. {
  14.   StreamReader reader = new StreamReader( new
  15.     IsolatedStorageFileStream( "SavedStuff.txt",  FileMode.Open,isoStore ) );
  16.  
  17.   // Several reader.ReadLines( ) calls elided.
  18.  
  19.   reader.Close();
  20. }

 

You can use isolated storage to persist reasonably sized data elements that enable partially trusted code to save and load information from a carefully partitioned location on the local disk. The .NET environment defines limits on the size of isolated storage for each application. This prevents malicious code from consuming excessive disk space, rendering a system unusable. Isolated storage is hidden from other programs and other users. Therefore, it should not be used for deployment or configuration settings that an administrator might need to manipulate. Even though it is hidden, however, isolated storage is not protected from unmanaged code or from trusted users. Do not use isolated storage for high-value secrets unless you apply additional encryption.

你可以使用隔离存储来保持合理大小的数据元素,使得部分受信任的代码可以从本地磁盘的仔细划分过的位置保存或者加载信息。.NET框架对每个应用程序的隔离存储的大小限制进行了定义。这样可以阻止恶意代码消耗过多的磁盘空间,使得系统不可用。隔离存储对于其它程序和用户是不可见的。因此,对于管理员可能需要进行维护的部署或者配置设置,不应该这样应用。然而,即使它是不可见的,隔离存储对于非托管代码或者信任的用户,并不是受保护的。除非你需要额外的加密,请不要为高度机密使用隔离存储。

To create an assembly that can live within the possible security restrictions on the file system, isolate the creation of your storage streams. When your assembly might be run from the Web or might be accessed by code run from the web, consider isolated storage.

为了创建一个在文件系统中存在于安全限制内的程序集,那么就隔离你的存储流的创建。当你的程序集能够从web运行或者被从web运行的代码访问的时候,就考虑隔离存储。

You might need other protected resources as well. In general, access to those resources is an indication that your program needs to be fully trusted. The only alternative is to avoid the protected resource entirely. Consider the Windows Registry, for example. If your program needs to access the Registry, you must install your program to the end user's computer so that it has the necessary privileges to access the Registry. You simply can't safely create a Registry editor that runs from the web. That's the way it should be.

你可能也需要其它的受保护的资源。一般来说,访问这些资源暗示着,你的程序需要被完全被信任。唯一的其他渠道就是完全避免使用这些受保护的资源。例如,考虑Windows注册表。如果你的程序需要访问注册表。你就不能安全的创建在web运行的注册表编辑器。本来就应该这样。

The .NET Security model means that your program's actions are checked against its rights. Pay attention to the rights your program needs, and try to minimize them. Don't ask for rights you don't need. The fewer protected resources your assembly needs, the less likely it will generate security exceptions. Avoid using secure resources, and consider alternatives whenever possible. When you do need higher security permissions for some algorithms, isolate that code in its own assembly.

.NET安全模型意味着你的程序的行为要根据它的权限来被检查。对你的程序需要的权限进行关注,努力使其最小。不要请求不需要的权限。你的程序集需要的受保护的资源越少,它生成的安全异常的可能性就越小。避免使用安全性的资源,只要可能就考虑替换方法。当你为了一些算法需要更高的安全许可时,将这些功能隔离在它自己的程序集里面。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值