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