对于许多ASP.NET开发人员而言,共享资源的访问是一个重大挑战,当开发Web表单和Web服务时就会遇到这样的挑战。微软公司的.NET拥有全新的用户授权和认证措施,大多数与安全相关的文章和书籍都用相当的篇幅解释表单认证,但是,与IIS、网络和操作系统安全相结合来理解ASP.NET安全架构是提供最佳解决方案的关健。
(图1)
图1描述了由IIS和ASP.NET提供的基本安全表示,它与ASP安全相比有根本不同。上面的图来自MSDN的网站。当有Web请求发生时,下面的事件会依次发生。
1、用户发出HTTP请求。
2、当Web请求发生时,它会由以SYSTEM帐户运行的IIS获得。SYSTEM帐户的功能非常强大,而且拥有所有类型的权限。IIS根据选择的认证类型进行认证,并为每名经过认证的用户创建一个访问令牌。如果选择了了匿名认证,它就会为该匿名用户创建一个访问令牌,缺省情况下是IUSR_MACHINE。另外,ISS还根据配置的授权类型进行认证。例如,IIS能够配置得只接受来自特定IP地址的请求。
3、IIS将请求和被认证用户的Windows访问令牌传递给aspnet_isepi.dll,这是一个注册为处理.aspx URL的ISAPI扩展。Aspnet_isepi.dll是一个IIS模块,是IIS和ASP.NET运行时间环境之间的一座桥。Aspnet_isapi通过命名管道向工作者进程转发该请求。
4、该工作者进程是托管着CLR的aspnet_wp.exe。缺省情况下,工作者进程以ASPNET帐户运行。当安装ASP.NET框架时,系统会创建该本地帐户。与功能强大的SYSTEM帐户不同的是,ASPNET帐户的功能十分有限。ASP.NET根据其认证配置对请求者进行认证。认证以XML格式配置在该项目的web.config文件中。如果ASP.NET被配置为Windows认证,它会接受任何来自IIS的令牌,而不会进行其它认证。另外,ASP.NET还授权对请求的资源和文件的访问。例如,FileAuthorizationModel可以用来检查用户是否具有访问请求的资源所需要的权限。对于Windows认证而言,用户的访问令牌为ACL。
5、如果整个过程发展到了这一步,应用软件就会使用特定的身份访问资源。缺省情况下,ASPNET进程帐户提供这一身份。但是,如果允许模仿,可以使用用户原来的身份或对模仿进行配置,使应用程序能够以特定的身份运行。
既然安全措施已经阐明,在假设NTFC的权限被设置为网络资源的情况下,用户就可以访问数据了。在进一步向前发展之前,有二个重要问题需要解决。一个是指定和定义访问UNC共享上文件和文件夹的任务,换句话说,也就是访问网络上共享的文件和文件夹。另一个问题是决定用来完成资源访问任务的身份。为了完成第一个任务,需要首先完成第二个任务。
有几种方法可以用来访问网络资源:
使用ASP.NET进程身份
使用匿名用户帐户
使用LogonUser API
使用服务性的组件(企业服务)
使用ASP.NET进程身份似乎有很明显的缺陷。缺省情况下,当应用程序试着访问资源时,ASP.NET进程身份提供一个身份(ASPNET)。最简单的解决方案是创建一个具有与远程计算机上相匹配的用户名和密码的本地帐户。大多数企业都会有庞大的内联网,因此这一方法是不切实际的。另外,知道是谁在访问资源也是非常重要的。尽管该方法足以访问网络资源,但效率不够高;第二个方法是使用匿名帐户,例如IUSR_MACHINE。与上面的原因相同,这种方法的效率显然也不高;第三种方法是使用LogonUser API,这种方法要求通过调用Win32 LogonUser API模仿一个特定的身份,还可以通过配置ASP.NET项目web.config文件中的<identity>元素进行模仿。据MSDN上的一篇文章称,不建议用户使用以上这些方法,应当避免在Windows 2000服务器上使用它们,因为它们要求向ASP.NET帐户进程授予“作为操作系统一部分运行”的权限,从而极大地降低了web应用程序的安全性。因此,该方法也不理想。最后,也是最可行的解决该问题的方法是使用配置为作为用于访问网络资源固定身份运行的服务性组件。这种方法听起来令人胆怯,但它是目前最好的解决方案,它的架构如下图所示:
(图2)
梅耶在http://msdn.microsoft.com/library/default.asp?url=/library/en-us/dnnetsec/html/SecNetch08.asp上发表的一一篇有关安全的文章中表示,在企业服务服务器应用程序中使用服务性组件有以下好处:
在使用的身份方面的灵活性,不必只依赖于ASP.NET身份。
受信任或权限较高的代码能够与主web应用程序隔离。
增加的进程跃距提高了攻击难度,它使得黑客更难跨越进程的边界,使用具有较高权限的进程。
如果需要手动处理LogonUser API调用的模仿,我们可以在一个与主Web应用程序隔离的进程中完成这一工作。
开发服务性组件
从COM+中接受服务的组合体被称作服务性组件。为了开发服务性组件,开发人员必须具备丰富的COM+技术经验。COM+应用程序不是传统意义上的应用程序,它不包含用户界面。COM+应用程序实际上是构成应用程序的组件、COM和.NET的容器,它不是新版的COM,也不是COM和DCOM的组合,而是遗传自MTS(微软事务服务)的一种技术。
下面是开发服务性组件所需要的步骤:
1、创建一个新类库项目,以开发作为Web应用程序类库的中间层组件。
2、添加合适的类、方法和属性。由于需要访问文件和文件夹,我们需要引入System.IO名字空间。
(图3)
3、创建一个Web窗体应用程序。
(图4)
现在就可以对组件进行测试了。为了在企业服务应用程序中实现较高的安全性,必须使用Windows认证实现模仿,这一工作可以在Web应用程序的web.config文件中实现。它使得服务性组件能够认证调用者,并根据调用者的身份作出授权决策。在开发期间,尽管组件还不是服务性组件,它仍然能够为访问共享文件和文件夹提供足够的安全性。
<authentication mode="Window" />
<identity impersonate="true" />
要进行测试,需要首先对类进行编译,然后将对象的引用添加到Web应用程序中。对类进行如下所示的初始化:
Dim objEnterprise As New AccessingSharedResources.dal_AccessNetwork()
4、创建强命名组合体
通过依次选择Start Menu --> Programs --> Microsoft Visual Studio .NET --> Visual Studio .NET Tools --> Visual Studio .NET Command Prompt运行Visual Studio .NET Command Prompt。
找到项目所在的目录,并输入下面的命令:sn -k KeyPair.snk。
上面的命令会创建一个公/私钥对,Visual Studio .NET IDE可以用它们给我们的组件一个强命名。另外需要注意的是,在项目目录中创建了一个KeyPair.snk文件。
打开AssemblyInfo.vb文件代码窗口,并添加下面的Assembly属性:
<Assembly: AssemblyKeyFile("KeyPair.snk")>
编译该项目。这将创建强命名的组合体。
5. Add the object to the GAC (Global Assembly Cache)
6、在GAC(全局组合体缓冲区)中添加对象
通过点击Start Menu --> Programs --> Administrative Tools --> Microsoft .NET Framework Configuration打开.NET框架配置工具。
点击Select Assembly Cache --> Select View List of Assemblies in the Assembly Cache浏览GAC中所有的组合体。
右击Assembly Cache图标,从弹出菜单中选择Add。
找到该项目的bin目录中的AccessingSharedResources.dll文件,并双击它。
注意:如果命令提示行窗口仍然在运行,输入gacutil /i AccessingSharedResources.dll,也能够将对象添加到GAC中。这是在GAC中添加对象的第二种方法。
7、添加System.EnterpiseServices.dll的引用
8、引入恰当的Enterprise Services名字空间
Imports System.EnterpriseServices
Imports System.Runtime.CompilerServices
Imports System.Reflection
9、在各个类中继承ServicedComponent类
Public Class dal_AccessNetwork
Inherits ServicedComponent
10、在支持服务性组件的AssemblyInfo.vb文件中添加与服务性组件相关的组合体属性。
引入System.EnterpriseServices名字空间
添加下面的代码:
'COM+应用程序名字
< Assembly: ApplicationName("AccessingSharedResources")>
'COM+激活类型
<Assembly: ApplicationActivation(ActivationOption.Server)>
11、设置AssemblyVersion:
据MSDN上的文章(http://msdn.microsoft.com/library/default.asp?url=/library/en-us/dnnetsec/html/SecNetch09.asp)称,当新项目创建时由Microsoft Visual Studio(r) .NET开发系统生成的缺省AssemblyVersion属性是<Assembly: AssemblyVersion("1.0.*")>。每当项目重建时,就会产生新的组合体版本,这也会产生识别服务性组件类的新的类识别符(CLSID)。如果使用Regsvcs.exe重