zoukankan      html  css  js  c++  java
  • 关于强命名

    由于最近换了一家公司工作,去的第二天就开始做项目,就在自己的项目去引用其他项目时,然后编译,却报“程序集生成失败 -- 引用的程序集没有强名称”的错误。原因:自己的项目是强命名程序集,强命名程序集不能引用普通程序集造成的。这时候,想起来曾经也碰到过这样的问题,所以解决起来也比较简单。今天拿出来写写,主要是想让曾经碰到同样问题的人一个解决问题的思路,仅此而已。若说的不好,还望大家批评指导。

        在解决这个问题之前,我想说说强签名程序集的概念以及由来,这样对我们解决问题的时候,知道问题一些本质东西。

      一、什么叫强命名程序集?

        我们知道,以前在Windows下开发程序时常会遭遇著名的“DLL Hell”问题(两个不同的公司可能开发处具有相同名称的程序集,如果将相同名称的程序集放置到同一个目录下,则会出现程序集覆盖现象,最后安装的程序集会覆盖前面的程序集,从而可能导致应用序不能正常运行,由此看来,仅靠名称来区分程序集是不足够的。),即动态链接库的向后兼容问题。微软在.Net产生前曾尝试使用COM组件的方式来解决DLL Hell问题,即使用Guid来唯一的标识每一个COM组件。但是,实际上使用COM组件(包括版本升级)也是一件颇为麻烦的事:为了运行COM组件就必须在组册表中对其进行注册,重新编译有可能破坏Guid从而导致原来引用此COM组件的程序不能正确运行等等。

        在.Net中,微软引入了一种新的解决方案:强命名程序集(Strong Name),以及与之配套的全局程序集缓存(GAC)来解决这个问题。

     .Net支持两种程序集:弱命名程序集和强命名程序集(注:.Net框架中没有弱命名程序集,只是为了和强命名程序集相对应而已)。 弱命名程序集和强命名程序集在结构上是相同的。他们都采用PE文件格式,包含PE表头,CLR表头,元数据和清单表。 区别在于:强命名程序集拥有一个发布者的公钥/私钥签名对,他们用于唯一的标识程序集的发布者。通过公钥/私钥对,我们可以对程序集进行唯一的标识,安全策略和版本策略。 强名称主要用处:就是防止dll被随意引用,另外控制版本,标识唯一性。

        在.NET中,强命名程序集应包含四个标识:Name(名称)、Version(版本号)、Culture(语言文化标识)、PublicToken(共有/私有密钥对),使用它们来唯一标识一个程序集,

    而不同产品前三个属性(Name、Version和Culture)完全相同的情况是有可能发生的,如此一来,这唯一标识程序集可重任就落到PublicToken的头上了。强命名的程序集正是使用RSA来保证PublicToken的唯一性,因为在理论上,非对称算法RSA生成的公钥/私钥对不会重复。.Net正是通过在编译项目时将指定的公钥/私钥对写入程序集来保证其唯一性。

         对于全局程序集缓存(GAC),安装有公共语言运行库的每台计算机都具有称为全局程序集缓存的计算机范围内的代码缓存。全局程序集缓存中存储了专门指定给由计算机中若干应用程序共享的程序集。

        在开发一般的、非共享的程序时,我们不需要使用强命名的程序集,仅将项目(Project)编辑成.DLL或者.EXE即可。但是,如果我们开发的是组件库、框架时,通过对程序集进行强命名,并使用将其部署到GAC中,可以保证我们的程序集不会出现版本问题。

       二、创建强命名程序集方法

        需要使用SN工具来生成密钥对。该工具位于安装.NET Framework SDK的Bin目录中,在命令行(visual studio 2005/2008/2010命令提示(开始-->程序-->microsoft visual studio 2005-->visual studio  tools-->visual studio 2005命令提示))中使用“ SN -k [驱动器号]:[放置密钥的目录][密钥名称].snk ”这样的语句可以生成密钥对文件。例如,SN -k d:MKeyStudio.snk,就会生成名为MKeyStudio.snk的密钥对文件,且存储在D盘根目录下。那如何让该密钥文件与项目的程序集建立关联呢?我们需要打开项目(Project)的AssemblyInfo.cs 文件,此文件具有一个程序集属性列表,默认情况下,在Visual Studio .NET 中创建项目时将包括这些属性。在代码中增加名为“AssemblyKeyFile”的属性,形式如下:[assembly:AssemblyKeyFile("d:MKeyStudio.snk")]   。此时,编译该项目即生成强命名的程序集项目。若MKeyStudio.snk文件在该项目的根目录(即与该项目解决方案文件处于同一个目录)下,则此时需要修改AssembleyInfo.cs文件中的“AssemblyKeyFile”属性,形式如下:[assembly:AssemblyKeyFile("MKeyStudio.snk")]。此方法是通过给程序集清单文件添加“AssemblyKeyFile”属性来实现强名称。还可以通过,右击该项目,出现下拉菜单,选择“属相”,打开“签名”Tab,勾上“为程序集签名”复选框,之后就可以选择一个强名称密钥文件作为该项目的签名就ok了。

    (出处:http://hi.baidu.com/jack1865/item/d14e4c94574d869ecc80e557

    强命名程序集(Strong Name Assembly)的概念
         因为不同的公司可能会开发出有相同名字的程序集来,如果这些程序集都被复制到同一
    个相同的目录下,最后一个安装的程序集将会代替前面的程序集。这就是著名的Windows “DLL
    Hell”出现的原因。
      很明显,简单的用文件名来区分程序集是不够的,CLR需要支持某种机制来唯一的标识一个程序集。这就是所谓的强命名程序集。
      一个强命名程序集包含四个唯一标志程序集的特性:文件名(没有扩展名),版本号,语言文化信息(如果有的话),公有秘钥。
      这些信息存储在程序集的清单(manifest)中。清单包含了程序集的元数据,并嵌入在程序集的某个文件中。
      下面的字符串标识了四个不同的程序集文件:

      “MyType,
    Version=1.0.1.0,


      Culture=neutral,
    PublicKeyToken=bf5779af662fc055”


      “MyType,
    Version=1.0.1.0,


      Culture=en-us,
    PublicKeyToken=bf5779af662fc055”


      “MyType,
    Version=1.0.2.0,


      Culture=neturl,
    PublicKeyToken=bf5779af662fc055”


      “MyType,
    Version=1.0.2.0,


      Culture=neutral,
    PublicKeyToken=dbe4120289f9fd8a”


      如果一个公司想唯一的标识它的程序集,那么它必须首先获取一个公钥/私钥对,然后将共有秘钥和程序集相关联。不存在两个两个公司有同样的公钥/私钥对的情况,正是这种区分使得我们可以创建有着相同名称,版本和语言文化信息的程序集,而不引起任何冲突。
      与强命名程序集对应的就是所谓的弱命名程序集。(其实就是普通的没有被强命名的程序集)。两种程序集在结构上是相同的。都使用相同的pe文件格式,PE表头,CLR表头,元数据,以及清单(manifest)。二者之间真正的区别在于:强命名程序集有一个发布者的公钥/私钥对签名,其中的公钥/私钥对唯一的标识了程序集的发布者。利用公钥/私钥对,我们可以对程序集进行唯一性识别、实施安全策略和版本控制策略,这种唯一标识程序集的能力使得应用程序在试图绑定一个强命名程序集时,CLR能够实施某些“已确知安全”的策略(比如只信任某个公司的程序集)。

    (出处:http://www.baike.com/wiki/%E5%BC%BA%E5%91%BD%E5%90%8D

    强名称是由程序集的标识加上公钥和数字签名组成的。其中,程序集的标识包括简单文本名称、版本号和区域性信息(如果提供的话)。  强名称是使用相应的私钥,通过程序集文件(包含程序集清单的文件,并因而也包含构成该程序集的所有文件的名称和散列)生成的。  Visual Studio 可以为程序集分配强名称。  强名称相同的程序集应该是相同的。 

    通过签发具有强名称的程序集,你可以确保名称的全局唯一性。   强名称还特别满足以下要求: 

    • 强名称依赖于唯一的密钥对来确保名称的唯一性。   任何人都不会生成与你生成的相同的程序集名称,因为用一个私钥生成的程序集的名称与用其他私钥生成的程序集的名称不相同。 

    • 强名称保护程序集的版本沿袭。强名称可以确保没有人能够生成你的程序集的后续版本。  用户可以确信,他们所加载的程序集的版本出自创建该版本(应用程序是用该版本生成的)的同一个发行者。 

    • 强名称提供可靠的完整性检查。   通过 .NET Framework 安全检查后,即可确信程序集的内容在生成后未被更改过。  但请注意,强名称中或强名称本身并不暗含信任级别,例如由数字签名和支持证书提供的信任。 

    在引用具有强名称的程序集时,你应该能够从中受益,例如版本控制和命名保护。    如果此具有强名称的程序集以后引用了具有简单名称的程序集(后者没有这些好处),则你将失去使用具有强名称的程序集所带来的好处,并依旧会产生 DLL 冲突。  因此,具有强名称的程序集只能引用其他具有强名称的程序集。

    (出处:http://msdn.microsoft.com/zh-cn/library/wd40t7ad(v=vs.110).aspx 

    改进的强命名:http://msdn.microsoft.com/zh-cn/library/hh415055(v=vs.110).aspx

  • 相关阅读:
    DNS放大攻击
    Java并发编程(四):并发容器(转)
    关注商业价值
    样式小记
    应用程序优化
    查看当前的连接和锁
    重命名你的数据库
    转:对XML插入操作
    对数据的分页再一次思考
    不浪费自己的时间,同时也不浪费别人的时间
  • 原文地址:https://www.cnblogs.com/I-am-Betty/p/3584807.html
Copyright © 2011-2022 走看看