在线时间:8:00-16:00
迪恩网络APP
随时随地掌握行业动态
扫描二维码
关注迪恩网络微信公众号
Security Context of ASP.NET是指ASP.NET的工作进程(Worker Process)在其他被访问的资源(例如SQL Server的服务或者网络共享文件夹)看来,是一个什么身份。以SQL Server为例,当ASP.NET应用程序代码尝试以Windows集成登录模式(而不是用SQL Server Login ID)来连接SQL Server时,SQL Server会认为是谁在尝试连接呢? 或者,ASP.NET程序可能需要访问一个以UNC路径表示的共享文件夹 \\fileserver\share,fileserver会认为是谁在尝试文件操作呢?
影响Security Context的因素很多,在分析这些因素的影响之前,首先要明确两点: (1)IIS服务本身的Service Account(默认为LocalSystem)不是一个影响因素 这是因为ASP.NET的程序并不工作在IIS的服务进程中,而是运行在一个称为“ASP.NET Worker Process”的工作进程中,这个工作进程类似一个Windows Service,但是在Windows Service列表中看不到。这个工作进程的控制程序是一个exe文件: asp_wp.exe(on Windows 2000)或者w3wp.exe(on Windows 2003)。 与此不同的是,很多其他的Service的Security Context都是Service Account,例如SQL Server的存储进程在尝试访问其他机器上的资源时,其身份就是MSSQLServer服务的启动帐号。 (2)在 Security Context这个问题上,ASP.NET Web应用程序网页和ASP.NET Web Service之间没有区别。因为两者都工作在ASP.NET Worker Process中。
实际影响ASP.NET Security的因素包括: (1)ASP.NET程序所在的Windows系统(更确切地说是IIS)的版本 (2)machine.config中的processModel设置 (3)ASP.NET的Impersonation设置 (4)IIS的匿名访问用户帐号设置 (5)IIS与被访问资源(如SQL Server)是否在同一台机器上 (6)被访问的外部资源是SQL Server,还是File System(例如一个UNC共享文件夹路径)
Windows 2000 Server with IIS 5.0先看Windows 2000 Server上的情况。 Machine.config的processModel
在\%windows%\Microsoft.NET\Framework\Version\Config目录中找到machine.config文件,其中有一个<processModel> tag: <processModel enable="true" ... userName="machine" password="AutoGenerate" ... /> 其中的userName="machine"就是指定使用本机ASPNET帐号(.\ASPNET)作为ASP.NET工作进程的默认账号。 这个默认帐号是可以修改的,如果开发人员将userName修改为一个域用户帐号: <system.web> <processModel enable="true" userName="domain\user" password="password" /> </system.web> 那么ASP.NET工作进程的身份就变成了domain\user。只要这个域用户帐号拥有需要的权限,那么machine.config所在机器上所有ASP.NET程序都可以访问域中其他服务器的资源,包括存取用UNC路径指定的文件。 如果指定userName="system",那么ASP.NET程序将以LocalSystem身份运行,可以存取几乎所有本地资源,因此非常危险!
无论machine.config指定哪个默认帐号,这个默认帐号都可以被应用程序的web.config设置的Impersonation覆盖,即特定应用程序可以以其他身份运行。 Web.config的Impersonation
Web.Config中有一个<identity>元素,可以用于设置本应用程序的身份,即所谓“扮演(Impersonation)”,即应用程序扮演成IIS服务请求者或者某个固定用户的身份,访问本地或者外部资源时,资源以为是被扮演的用户在访问一样。 扮演有两种可能: (1) 扮演IIS服务请求者,即浏览器客户端的身份 在web.config中设置: <identity impersonate="true" /> ASP.NET进程将扮演http/https请求者的身份。具体是什么帐号,就跟IIS的安全性设定有关了: 如果IIS允许匿名访问,那么缺省状态下,被扮演的将是Iuser_Machine帐号,即在IIS安全设置中用Enable anonymous access指定的帐号。如果修改过,那被扮演的就是修改过的帐号。 如果IIS不允许匿名访问,那么浏览器请求者的身份肯定是一个Windows帐号,这个帐号就是被扮演的对象。 (2)扮演一个固定用户 设置扮演固定用户身份,需要为<identity>元素指定userName 和password两个 attributes: <identity impersonate="true" userName="MyServiceAccount" 显然,将password这样明码写在web.config中是不合适的。推荐的办法是使用Aspnet_setreg.exe工具,将这种信息加密后保存到注册表中。
无论扮演哪个帐号,微软都不推荐使用扮演,一方面是安全性问题(被扮演的帐号可能有一些程序并不需要的多余权限,可能被利用),另一方面是可伸缩性问题(Scalability),因为在访问SQL Server等资源时,无法利用连接池等手段。 资源服务器与IIS分离以上提到的 .ASPNET,IUser_Machine都是本机帐号,即仅在IIS所在的机器上有效,如果ASP.NET代码试图访问其他机器上的资源,例如SQL Server或者UNC路径,那么资源服务器是不认的。在文件服务器看来,似乎是一个'NT AUTHORITY \ ANONYMOUS LOGON'帐号在试图访问,对于SQL Server,如果代码采用Windows集成安全模式登录,SQL Server会报错:(null)帐号登录失败。 有几种方法可以解决这个问题: (1)放开资源服务器上的Guest帐号 (2)将IIS的匿名访问帐号改成一个domain\user (3)在web.config设置扮演,扮演一个domain\user 第一个方法是安全性方面最忌讳的事情,所以不要这样干。后面两个方法实质一样,就是以一个资源服务器能认可的身份去访问。这种方法也有一个问题:domain user可能具备一些本来不需要的权限。更为麻烦的是,如果网管或是什么人修改了那个帐号的密码,应用程序的运行就会出问题。再有,如果想要扮演domain user,密码的保存令人头痛:不能明文放在web.config中,只好加密放在注册表中。密码加密了,加密用的key又成了烫手山芋,放在明处怕人看见,放在暗处又怕丢。 所以真正的好办法是:升级IIS所在的Windows 2000,采用Windows Server 2003!
Windows Server 2003 with IIS 6.0
再看Windows Server 2003上的情况。 Windows Server 2003将IIS的内核重写了,因此其IIS 6.0在很多方面都跟Windows 2000的IIS 5.0很不一样。从ASP.NET Security Context的角度看,最大的不同在于: (1)ASP.NET工作进程的控制程序不同:不是aspnet_wp.exe,而是w3wp.exe。 (2)尽管在安装.NET Framework时也创建了.\ASPNET帐号,machine.config中也指定了processModel userName=”machine”,其含义却不是使用.\ASPNET帐号,而是使用NTAuthority\Network Service,作为ASP.NET工作进程的默认身份。 这个NetworkService帐号是Windows 2003引入的一个新的特殊帐号,与LocalSystem相似,这个帐号是个虚拟帐号、可以作为Service的启动帐号,但是它对本地资源的权限非常有限,因此以这个帐号为启动帐号的服务进程,对本地文件等资源几乎没有什么权限,从而Windows系统的安全性可以得到更好保证。 对ASP.NET程序来说,ASP.NET工作进程缺省以Network Service身份运行,为程序代码访问IIS之外的资源服务器提供了极大方便: 当程序代码试图访问其他机器上的资源(SQL Server或者UNC)时,其身份将不再是ANONYMOUS LOGON,而是IIS机器帐号:Domain\MachineName$。这就是所谓“代表(Delegate)”机制。NetworkService就像一个小职员,在公司内部地位很低,到了外面却代表整个公司。 因此,在Windows 2003的IIS上运行的ASP.NET 程序,如果需要访问其他机器上的SQL Server或者文件资源,只需要在资源服务器上为IIS计算机账号授权即可,既不需要修改IIS匿名访问帐号,也不需要设置扮演,省去很多麻烦。 以SQL Server为例,如果需要允许IIS上的程序登录并访问某个数据库,只需要运行如下 SQL脚本: exec sp_grantlogin N'DomainName\IISMachineName$' use [DatabaseName] exec sp_grantdbaccess N'DomainName\IISMachineName$', N'IISMachineName$' exec sp_addrolemember N'db_owner', N'IISMachineName$' 这样使用计算机账号进行资源访问,还可以得到两个好处: (1)数据库连接可以采用Windows集成安全模式,连接字串可以光明正大地明文保存在web.config中,如: Integrated Security=SSPI;Initial Catalog=<DatabaseName>;Data Source=<ServerName>; (2)普通情况下,计算机账号对其他网络资源没有任何权限,因此整个系统符合Least Privilege原则,不会有什么不放心的权限。 |
请发表评论