第三章 共享程序集和强命名程序集

1、本章重点:如何创建可由多个应用程序共享的程序集。Microsoft .NET Framework随带的程序集就是典型的全局部署程序集,因为所以托管应用程序都要使用Microsoft在.NET Framework Class Library(FCL)中定义的类型。

2、CLR支持两种程序集:弱命名程序集(weakly named assembly)和强命名程序集(strongly named assembly).

弱命名和强命名程序集结构完全相同,二者真正区别在于,强命名程序集使用发布者的公钥/私钥进行了签名。这一个密钥允许对程序集进行唯一性的标识、保护和版本控制,并允许程序集部署到用户机器的任何地方。由于程序集被唯一性地标识,所以当应用程序绑定到强命名程序集时,CLR可以应用一些已知安全的策略。

3、强命名程序集具有4个重要特性,它们共同对程序集进行唯一标识:文件名(不计扩展名)、版本号、语言文化和公钥。创建强命名程序集第一步是用.NET Framework SDK和Microsoft Visual Studio随带的Strong Name实用程序(SN.exe)获取密钥。

SN -k MyCompany.snk

这告诉SN.exe创建MyCompany.snk文件,文件中包含二进制形式的公钥和私钥。公钥太大,人们设计了公钥标记(public key token)。公钥标记是公钥的64位哈希值。

4、全局程序集缓存

由多个应用程序访问的程序集必须放到公认的目录,而且CLR在检测到对该程序集的引用时,必须知道检查该目录。这个公认位置就是全局程序集缓存(Global Assembly Cache,GAC)。

GAC目录是结构化的:其中包含许多子目录,子目录名称用算法生成。永远不要讲程序集文件手动复制到GAC目录;相反,要用工具完成这项任务,常用的工具是GACUtil.exe。

向GACUtil.exe传递弱命名程序集的文件名会报错:“将程序集添加到缓存失败:尝试安装没有强名称的程序集。”

GACUtil.exe的/i开关将程序集安装到GAC,/u开关从GAC卸载程序集。

为什么要在GAC中“注册”程序集?

假定两家公司都生成了名为OurLibrary的程序集,两个程序集都由一个OurLibrary.dll文件构成。这两个文件显然不能存储到同一个目录,否则最后一个安装的会覆盖第一个,造成应用程序被破坏。相反,将程序集安装到GAC,就会在%SystemRoot%\Microsoft.NET\Assembly目录下创建专门的子目录,程序集文件会复制到其中一个子目录。

5、强命名程序集能防篡改

用私钥对程序集进行签名,并将公钥和签名嵌入程序集,CLR就可验证程序集未被修改或破坏。程序集安装到GAC时,系统对包含清单的那个文件的内容进行哈希处理,将哈希值与PE文件中嵌入的RSA数字签名进行比较(在用公钥解除了签名之后)。如果两个值完全一致,表明文件内容未被篡改。此外,系统还对程序集的其他文件的内容进行哈希处理,并将哈希值与清单文件的FileDef表中存储的哈希值进行比较。任何一个哈希值不匹配,表明程序集至少有一个文件被篡改,程序集将无法安装到GAC。

应用程序需要绑定到程序集时,CLR根据被引用程序集的属性(名称、版本、语言文化、公钥)在GAC中定位该程序集。找到被引用的程序集就返回包含它的子目录,并加载清单所在的文件。如果在任何位置都找不到程序集,那么绑定失败,抛出System.IO.FileNotFoundException异常。

6、"运行时"如何解析类型引用

解析引用的类型时,CLR可能在以下三个地方找到类型:

相同文件;不同文件,相同程序集;不同文件,不同程序集。

下图说明了对于引用了方法或类型的IL代码 CLR是怎样通过元数据来定位定义了类型的程序集文件。

对于CLR,所有程序集都根据名称、版本、语言文化、公钥来识别。但GAC根据名称、版本、语言文化、公钥和CPU架构来识别。在GAC中搜索程序集时,CLR判断应用程序当前在什么类型的进程中运行,是32位x64(可能使用WoW64技术),64位x64,还是32位ARM。然后,在GAC中搜索程序集时,CLR首先搜索程序集的CPU架构专用版本。如果没有找到符合要求的,就搜索不区分CPU的版本。

 

posted @ 2018-01-15 21:52  LEITION  阅读(222)  评论(0编辑  收藏  举报