UML软件工程组织

.NET应用自动部署窗体技术详解
作者:Hector J. Correa;仙人掌工作室译 
  .NET框架提供了一些新的工具简化.NET胖客户端程序的部署,本文阐述了.NET自动部署技术的基础知识,以及防止用户错误下载黑客程序和病毒代码的安全机制。

  .NET的自动部署技术构造在.NET框架之中,它使得应用程序能够通过HTTP连接从远程服务器按需下载程序集。有了这个功能,我们可以把胖客户端应用程序发布到一个Web服务器,确保用户下一次使用应用程序时总是自动得到程序的最新版本。设想一下吧:再也不必用CD来发布升级软件,再也不必在电话中向用户反复解释因版本冲突引起的问题!

  .NET提供了大量用于实现自动部署机制的功能,例如,.NET知道如何从一个远程服务器下载程序集并把它保存到用户的磁盘缓冲区,而且只有当远程服务器上又有了新的版本时才再次下载——所有这些功能都已经构建到了.NET框架之中。

一、自动部署执行文件

  自动部署.NET Windows窗体应用程序的机制可分为两部分,第一部分是自动部署主执行文件,第二部分是允许用户使用应用程序时下载应用的其余部分。

  首先我们来看看第一部分。让用户访问主执行文件很简单,只要把执行文件发布到Web服务器,然后把URL告诉用户。例如,假设执行文件的名字为loader.exe,我们可以在企业的Web服务器上创建一个虚拟目录,然后把执行文件的位置http://www.mycompany.com/myapp/loader.exe告诉每一个用户。

  用户只要用浏览器打开这个URL,或者在“开始”菜单“运行”输入框输入这个URL,就可以运行loader.exe执行文件。另外,我们还可以创建一个Web页面,加入一个指向loader.exe的HTML HREF标记。



图1:从Web服务器发布执行文件


  下面我们运行一下本文下载包中的一个.NET执行文件。

  ⑴ 从本文最后下载文件,将文件解压缩到C:\CodeDownloadDemo文件夹。

  ⑵ 在IIS中创建一个虚拟文件夹CodeDownloadDemo。

  ⑶ 将虚拟文件夹映射到C:\CodeDownloadDemo\Loader\Bin文件夹。

  ⑷ 启动IE浏览器,输入下面的URL:http://localhost/CodeDownloadDemo/loader.exe。

  看到loader应用程序在浏览器外面运行了吗?应用程序一旦开始运行,即使关闭了浏览器,我们仍可以访问应用程序。对于任何其他.NET应用程序,我们都可以照此办理,只要将它放到Web服务器上,然后用浏览器启动即可。

二、UrlScan工具的影响

  只要Web服务器上没有安装UrlScan工具,上面的例子就可以毫无问题地运行。UrlScan工具随同IIS Lockdown工具一起发行,它的功能是禁止向Web服务器发送非法的请求。默认情况下,UrlScan工具认为包含执行文件的URL都是非法的,因此如果Web服务器上安装了UrlScan,对http://localhost/CodeDownloadDemo/loader.exe的访问将被禁止。

  要检查系统中是否已经安装了UrlScan工具,可以在控制面板中打开“添加或删除程序”,查看“当前安装的程序”清单。

  另外,我们还可以修改UrlScan的默认配置,使其允许对执行文件的请求,即修改一下UrlScan用来检测合法/非法请求的INI配置文件。UrlScan的配置文件保存在c:\windows\system32\inetsvr\urlscan\urlscan.ini,下面是该文件的一个片断:


[DenyExtensions]
   ; Deny executables that could 
   ; run on the server
   .was_exe
   .bat
   .cmd
   .com


  这个配置文件片断中,.exe文件扩展名已经改成了.was_exe,表示.exe扩展名不再被禁止。但必须注意的是,这是解除UrlScan限制的一种简便方法,可能带来安全风险。对于正式为用户提供服务的Web服务器,修改配置之前务必阅读UrlScan的文档或询问网络管理员。

  修改UrlScan的INI配置文件之后,必须重新启动IIS服务器,才能让修改生效。例如,在命令行环境中执行IISRESET.exe就可以重新启动IIS服务器。

三、自动部署应用程序的其余部分

  前面我们了解了如何自动部署一个执行文件,这种办法对于loader(约45 KB)之类的小型应用程序有效,但通常的应用程序都要大于45 KB,例如,如果应用程序有3 MB,我们不应该让用户每次运行时都重新下载一个3 MB的文件。解决这个问题需要用到.NET自动部署机制的第二部分技术。

  和前面的办法相比,一种更好的办法是将主执行程序安装到用户的硬盘上,让这个主执行程序按需下载应用程序的其余部分。例如,当用户要用到应用程序的Invoicing模块时就下载Invoicing部分,要用到Employees模块时就下载Employees部分(参见图2)。



图2:自动部署一个应用程序


  这种类型的部署通常称为“滴流”部署(Tickle Down Deployment)。.NET框架提供了支持滴流布署技术的必要工具类,即System.Reflection名称空间中的Assembly。Assembly类能够从远程服务器下载一个程序集,并在本地缓冲以供以后引用。例如,利用下面的代码可以从http://localhost/CodeDownloadDemo/Loader/下载ModuleA.dll程序集,然后从该程序集创建EmployeeForm类的实例:


'指定URL
   Dim URL As String
   URL = _
   "http://localhost/CodeDownLoadDemo/ModuleA.DLL"
   '从指定的URL装入程序集
   Dim a As [Assembly]
   a = [Assembly].LoadFrom(URL)
   '获得一个EmployeeForm类的引用
   Dim t As Type = a.GetType("ModuleA.EmployeeForm")
   '创建窗体的实例,并显示出窗体
   Dim o As Object = Activator.CreateInstance(t)
   o.Show()


  这个代码片断虽然简单,却用到了.NET框架许多值得关注的特性。下面我们就来逐一分析这些特性。

  首先,[Assembly].LoadFrom这行代码利用HTTP协议下载一个DLL。在本例中,URL指向localhost,但它同样也可以指向一个远程服务器,例如http://www.mycompany.com/myapp。这就是说,我们只要一行代码,并指定一个适当的URL,其余工作就全交给.NET了,不管程序集是本地的还是远程的。

  其次,从远程服务器下载得到一个DLL之后,a.GetType这行代码从该DLL提取一个类的引用。注意,类的名称以字符串的形式指定,这意味着,我们可以在运行时临时决定要引用的类的名称。这一点非常重要,因为现在我们可以在运行时决定要引用的是ModuleA.EmployeeForm,还是ModuleA.InvoiceForm。对于VB.NET和C#之类强类型的语言,这一特性显得尤其宝贵,它提供的灵活性是这类语言中非常罕见的。

  最后,Activator.CreateInstance(t)这行代码实际创建了EmployeeForm类的一个实例。有了类的实例之后,接下来就可以调用它的方法,设置它的属性。在上面的例子中,我们调用了EmployeeForm类的Show方法。

四、localhost与127.0.0.1的区别

  当我们指定的URL是“http://localhost”形式时,前面两节介绍的办法都不会出现问题。但是,如果我们改用http://127.0.0.1形式的URL,就会遇到问题。例如,如果用http://127.0.0.1/CodeDownloadDemo/loader.exe这个URL来打开loader.exe,就会看到类似图3的错误信息:



图3:用127.0.0.1访问时出现的错误


  系统的配置不同,具体的错误信息也不同,但不管错误信息到底是什么,用http://127.0.0.1总是可以看到与安全有关的错误信息。

  当我们通过一个URL来运行应用程序时,应用程序可能来自一个远程服务器。但是,.NET不能肯定我们想要运行的代码是来自一个可信任的服务器,还是一个受限制的站点。.NET对远程代码采用的安全策略相当复杂,简单地说,.NET把那些不包含句点符号(“.”)的URL视为本地Intranet的URL。默认情况下,.NET允许运行来自Intranet站点的代码。另一方面,.NET把那些包含了句点符号的URL(例如http://127.0.0.1)视为Internet地址,除非明确地设定某个URL是一个安全的位置,否则.NET默认不允许运行Internet URL的程序代码。

  安全策略是.NET框架必不可少的组成部分,如果没有安全策略,允许用户将浏览器指向任何URL下载.NET执行文件并自动运行,那只会把网络变成病毒编写者的天堂。有了.NET安全策略,我们就可以保护用户,避免用户下载和运行来源不明的代码。

  也许大家已经知道,.NET框架是一个与操作系统紧密集成的系统,安全机制是这种紧密集成特别明显的领域之一。.NET安全策略不仅强大,而且具有高度可配置的特点。下面我们就来了解一下这些安全策略的基本组织,以及如何配置安全策略允许用户从可信任的URL下载执行文件。

五、.NET和IE安全配置

  显然,要想让用户通过HTTP协议运行某个执行文件,第一个可以配置安全选项的位置应该是IE浏览器。具体的操作步骤是,启动IE浏览器,转到“工具”菜单,打开“Internet选项”,选择“安全”选项卡,再依次点击“受信任的站点”、“站点”。

  我们可以把http://127.0.0.1作为一个受信任的站点加入。注意,必须清除了“对该区域中的所有站点要求服务器验证(https:)”选项之后,才能将http://127.0.0.1作为可信任站点加入。



图4:添加一个信任站点


  现在http://127.0.0.1已经是一个可信任的站点了,如果我们再次用http://127.0.0.1/CodeDownloadDemo/Loader.exe这个URL来执行loader.exe,应用程序可以启动,不过.NET仍会提示还有一些安全问题有待解决(如图5)。



图5:应用程序在部分受信任的安全上下文中运行


  这一次我们看到loader应用程序正式运行了,但有一则提示信息告诉我们应用程序当前在一个部分受信任的安全上下文中运行,因此应用程序的某些功能可能无法使用。例如,如果我们试图从Employees窗体装入数据,就会看到一个安全错误(如图6所示),这是因为该窗体试图从localhost上SQL Server的Northwind数据库读取数据,但我们还没有授权它可以执行这一操作。



图6:试图访问指定站点之外的资源时.NET提示错误信息


  另外请注意,应用程序的标题条上自动加上了表示来源的“127.0.0.1”。

、.NET安全和框架配置工具

  虽然IE浏览器允许配置一些.NET应用的安全选项,但不全面。

  要访问.NET应用的全部安全选项,必须使用.NET Framework配置工具。这个工具是.NET框架的一部分,而不是VS.NET的一部分,这意味着,用户只要安装了.NET框架,他就有了相应的配置工具。启动.NET Framework配置工具的步骤是:打开Windows控制面板,选择“管理工具”,然后选择“Microsoft .NET Framework配置”。利用这个工具,我们可以配置.NET安全策略,确定允许信任哪些地址,以及对各个地址的信任程度。

  全面介绍.NET安全策略以及配置安全策略的工具已经超出了本文的范围,但我们可以举出简单的例子,了解配置代码组和权限集的基本方法(请参见图7)。



图7:.NET框架配置工具


  代码组列举了哪些代码是可以信任的,哪些代码必须禁止访问。一般地,我们可以将图7默认设置的代码组与IE浏览器安全设置对话框中的“区域”相对应。

  权限集是一种把多个权限用单一名称组织起来的办法。例如,图8显示了默认授予“本地Intranet”权限集的权限清单。



图8:Intranet权限集


  右击一个节点可以创建自定义的代码组或权限集。例如,只要按照下面的步骤授予http://127.0.0.1的URL全部信任权限,前面的例子就不会再显示任何安全错误信息:

  ⑴ 打开“代码组”分支,右击All_code,选择“新建”,如图9。



图9:创建自定义的代码组和权限集


  ⑵ 输入新建代码组的名称,例如“MyCodeGroupFor127”,点击“下一步”。

  ⑶ 如图10,在“选择此代码组的条件类型”中,选择“URL”,然后输入“http://127.0.0.1/*”作为可信任的URL,点击“下一步”。



图10:设置代码组的条件类型


  ⑷ 最后,如图11,选择权限集FullTrust(完全信任),点击“下一步”,再点击“完成”。



图11:将权限集指定给代码组


  现在,如果我们再打开IE浏览器,用http://127.0.0.1/CodeDownloadDemo/Loader.exe这个URL启动loader.exe程序,程序运行时不会出现任何安全错误信息。即使我们从File菜单选择Employee Form,从数据库装入Employee的数据,同样不会出现错误信息。

  在上面这个例子中,我们将FullTrust授予了一个URL,仅用于演示当然没有问题,但在正式的生产环境中,授权应当谨慎,只能将保证应用程序能够正常工作的最小权限授予指定的URL。

七、部署.NET安全策略

  在前面一节中,我们创建了一个安全策略信任来自http://127.0.0.1的代码。在实际应用中还存在这样一个问题,即我们应当方便用户,不能要求每一个用户按照同样的步骤设置安全策略。

  解决办法很简单,设置好安全策略之后,我们还可以将安全策略分发给用户,用户只需一次点击就可以完成全部设置。

  首先我们要创建一个部署包,它将通过Windows安装文件(.MSI)文件把安全策略安装到用户的机器上。操作方法是:右击“运行库安全策略”,选择“创建部署包”,如图12。



图12:创建一个部署包


  部署包的安全策略级别分三种:企业,计算机,用户。本例中,我们创建一个计算机策略的部署包,如图13。注意部署包的扩展名是.MSI。



图13:设置要部署的安全策略为“计算机”策略


  创建好部署包之后,可以将它分发给用户。只要双击运行.msi文件,Windows安装程序就会自动安装.msi文件中定义的安全策略。另外,网络管理员还可以通过适当的配置,将配置安全策略的部署包自动发布给每一个用户。

八、深入理解Assembly.LoadFrom

  现在,我们来看看用Assembly.LoadFrom从远程服务器下载一个程序集时背后发生的事情,以下面的代码为例:


'指定URL
   Dim URL As String
   URL = _
   "http://localhost/CodeDownLoadDemo/ModuleA.DLL"
   '从指定的URL装入程序集
   Dim a As [Assembly]
   a = [Assembly].LoadFrom(URL)


  当.NET执行LoadFrom方法时,它访问http://localhost/CodeDownloadDemo,寻找Web服务器上的ModuleA.dll程序集。在此过程中,.NET会检查以前是否下载过该程序集,如果从来没有下载过,.NET就下载该程序集,并把它保存到.NET程序集下载缓冲区。

  第二次运行同样的代码时,.NET知道该程序集以前已经下载过一次,如果Web服务器上程序集的版本和本地程序集下载缓冲区中的版本一样,.NET就使用已经下载到磁盘上的程序集。

  假设我们现在第三次运行上述代码,.NET检测到Web服务器上程序集的版本要比本地缓冲的版本新,这时.NET就会重新下载新版的程序集,把它保存到程序集下载缓冲区,并运行它。程序集下载缓冲区是位于\windows\assembly\download的一个特殊文件夹。

  必须指出的是,在比较程序集的本地版本和远程版本哪一个更新时,.NET的判断依据是程序集的时间标记,而不是程序集的版本号。这一点很重要,特别地,如果有多个程序员协同开发和编译程序集,应当注意计算机的时间设置问题。

九、当Web服务器不可用时

  如果执行Assembly.LoadFrom时,http://localhost/CodeDownLoadDemo/的Web服务器不可用,例如,用户的Internet连接出了故障,或者用户正在旅途中使用笔记本,这时应该怎么办?在这种情况下,LoadFrom执行失败,用户不能从远程服务器上的程序集装入类。

  有一种解决办法,虽然不那么完美,但确实行得通,即用户只要把浏览器设置成脱机工作模式就可以了。如此设置之后,Assembly.LoadFrom就自动知道它应该使用程序集的下载缓冲区。

十、结束语

  上面介绍的所有技术都有一个限制,即如果要让自动部署技术能够在用户的机器上正常发挥,所有机器必须安装.NET框架。虽然.NET框架是免费的,但不一定每一个用户都会去安装它。如果应用程序一定要求用户下载和安装20 MB的.NET框架,用户对应用程序的印象可能会受到影响。

  越来越多的新计算机会预先装好.NET框架,所以该问题的影响应该越来越小。目前临时的解决办法是,用Install Shield或Wise Installer之类的工具创建一个典型配置的.NET框架安装包,实现.NET框架自动安装。

  .NET自动部署是一种非常强大的技术,它能够有效地减少部署胖客户端程序过程中面临的问题。充分运用.NET自动部署技术,我们可以保证用户总是使用最新版本的代码,却不必要求用户频繁地去访问某个网站下载更新软件。

  .NET自动部署技术一项很重要的特性是安全,它使得用户既可以从指定的远程地点下载程序,同时有效地保障用户不会意外地运行来源不明的代码。

下载本文的代码:dotNetAutoDeploycode.zip

原文

来源:赛迪网

 

版权所有:UML软件工程组织