在ASP.NET應(yīng)用程序中使用身份模擬(Impersonation)
摘要
缺省情況下,,ASP.NET應(yīng)用程序以本機(jī)的ASPNET賬號(hào)運(yùn)行,,該賬號(hào)屬于普通用戶組,權(quán)限受到一定的限制,,以保障ASP.NET應(yīng)用程序運(yùn)行的安全,。但是有時(shí)需要某個(gè)ASP.NET應(yīng)用程序或者程序中的某段代碼執(zhí)行需要特定權(quán)限的操作,比如某個(gè)文件的存取,,這時(shí)就需要給該程序或相應(yīng)的某段代碼賦予某個(gè)賬號(hào)的權(quán)限以執(zhí)行該操作,,這種方法稱之為身份模擬(Impersonation)。本文介紹了在ASP.NET應(yīng)用程序中使用身份模擬的幾種方法,,并比較了它們各自適用的范圍,。
在閱讀本文之前,建議您先閱讀文章:《ASP .NET 中的身份驗(yàn)證:.NET 安全性指導(dǎo)》 以便對(duì)ASP.NET的安全控制有一個(gè)總體的了解,。
目錄
ASP.NET中的身份模擬
ASP.NET 通過使用身份驗(yàn)證提供程序來實(shí)現(xiàn)身份驗(yàn)證,,一般情況下,ASP.NET的身份驗(yàn)證提供程序包括表單身份驗(yàn)證,、Windows身份驗(yàn)證和Passport身份驗(yàn)證3種,。當(dāng)通過身份驗(yàn)證后,ASP.NET會(huì)檢查是否啟用身份模擬,。如果啟用,,ASP .NET 應(yīng)用程序使用客戶端標(biāo)識(shí)以客戶端的身份有選擇地執(zhí)行。否則,,ASP.NET應(yīng)用程序使用本機(jī)身份標(biāo)識(shí)運(yùn)行(一般使用本機(jī)的ASPNET賬號(hào)),,具體流程如下圖所示:
在ASP.NET應(yīng)用程序中使用身份模擬一般用于資源訪問控制,主要有如下幾種方法:
模擬IIS認(rèn)證賬號(hào)
這是最簡單的一種方法,,使用經(jīng)過IIS認(rèn)證的賬號(hào)執(zhí)行應(yīng)用程序,。您需要在Web.config文件中添加<identity>標(biāo)記,并將impersonate屬性設(shè)置為true:
<identity impersonate="true" /> 在這種情況下,,用戶身份的認(rèn)證交給IIS來進(jìn)行,。當(dāng)允許匿名登錄時(shí),IIS將一個(gè)匿名登錄使用的標(biāo)識(shí)(缺省情況下是IUSR_MACHINENAME)交給ASP.NET應(yīng)用程序,。當(dāng)不允許匿名登錄時(shí),,IIS將認(rèn)證過的身份標(biāo)識(shí)傳遞給ASP.NET應(yīng)用程序。ASP.NET的具體訪問權(quán)限由該賬號(hào)的權(quán)限決定,。
模擬指定的用戶賬號(hào)
當(dāng)ASP.NET應(yīng)用程序需要以某個(gè)特定的用戶賬號(hào)執(zhí)行,,可以在Web.config文件的<identity>標(biāo)記中指定具體的用戶賬號(hào):
<identity impersonate="true" userName="accountname" password="password" /> 這時(shí)該ASP.NET應(yīng)用程序的所有頁面的所有請(qǐng)求都將以指定的用戶賬號(hào)權(quán)限執(zhí)行,。
在代碼中模擬IIS認(rèn)證賬號(hào)
在代碼中使用身份模擬更加靈活,可以在指定的代碼段中使用身份模擬,,在該代碼段之外恢復(fù)使用ASPNET本機(jī)賬號(hào),。該方法要求必須使用Windows的認(rèn)證身份標(biāo)識(shí)。下面的例子在代碼中模擬IIS認(rèn)證賬號(hào):
Visual Basic .NET
Dim impersonationContext As System.Security.Principal.WindowsImpersonationContext Dim currentWindowsIdentity As System.Security.Principal.WindowsIdentity currentWindowsIdentity = CType(User.Identity, System.Security.Principal.WindowsIdentity) impersonationContext = currentWindowsIdentity.Impersonate() ‘Insert your code that runs under the security context of the authenticating user here. impersonationContext.Undo() Visual C# .NET
System.Security.Principal.WindowsImpersonationContext impersonationContext; impersonationContext = ((System.Security.Principal.WindowsIdentity)User.Identity).Impersonate(); //Insert your code that runs under the security context of the authenticating user here. impersonationContext.Undo(); 在代碼中模擬指定的用戶賬號(hào)
下面的例子在代碼中模擬指定的用戶賬號(hào):
Visual Basic .NET
<%@ Page Language="VB" %> <%@ Import Namespace = "System.Web" %> <%@ Import Namespace = "System.Web.Security" %> <%@ Import Namespace = "System.Security.Principal" %> <%@ Import Namespace = "System.Runtime.InteropServices" %> <script runat=server> Dim LOGON32_LOGON_INTERACTIVE As Integer = 2 Dim LOGON32_PROVIDER_DEFAULT As Integer = 0 Dim impersonationContext As WindowsImpersonationContext Declare Auto Function LogonUser Lib "advapi32.dll" (ByVal lpszUsername As String, _ ByVal lpszDomain As String, _ ByVal lpszPassword As String, _ ByVal dwLogonType As Integer, _ ByVal dwLogonProvider As Integer, _ ByRef phToken As IntPtr) As Integer Declare Auto Function DuplicateToken Lib "advapi32.dll"(ByVal ExistingTokenHandle As IntPtr, _ ImpersonationLevel As Integer, _ ByRef DuplicateTokenHandle As IntPtr) As Integer Public Sub Page_Load(s As Object, e As EventArgs) If impersonateValidUser("username", "domain", "password") Then ‘Insert your code that runs under the security context of a specific user here. undoImpersonation() Else ‘Your impersonation failed. Therefore, include a fail-safe mechanism here. End If End Sub Private Function impersonateValidUser(userName As String, _ domain As String, password As String) As Boolean Dim tempWindowsIdentity As WindowsIdentity Dim token As IntPtr Dim tokenDuplicate As IntPtr If LogonUser(userName, domain, password, LOGON32_LOGON_INTERACTIVE, _ LOGON32_PROVIDER_DEFAULT, token) <> 0 Then If DuplicateToken(token, 2, tokenDuplicate) <> 0 Then tempWindowsIdentity = new WindowsIdentity(tokenDuplicate) impersonationContext = tempWindowsIdentity.Impersonate() If impersonationContext Is Nothing Then impersonateValidUser = False Else impersonateValidUser = True End If Else impersonateValidUser = False End If Else impersonateValidUser = False End If End Function Private Sub undoImpersonation() impersonationContext.Undo() End Sub </script> Visual C# .NET
<%@ Page Language="C#"%> <%@ Import Namespace = "System.Web" %> <%@ Import Namespace = "System.Web.Security" %> <%@ Import Namespace = "System.Security.Principal" %> <%@ Import Namespace = "System.Runtime.InteropServices" %> <script runat=server> public const int LOGON32_LOGON_INTERACTIVE = 2; public const int LOGON32_PROVIDER_DEFAULT = 0; WindowsImpersonationContext impersonationContext; [DllImport("advapi32.dll", CharSet=CharSet.Auto)] public static extern int LogonUser(String lpszUserName, String lpszDomain, String lpszPassword, int dwLogonType, int dwLogonProvider, ref IntPtr phToken); [DllImport("advapi32.dll", CharSet=System.Runtime.InteropServices.CharSet.Auto, SetLastError=true)] public extern static int DuplicateToken(IntPtr hToken, int impersonationLevel, ref IntPtr hNewToken); public void Page_Load(Object s, EventArgs e) { if(impersonateValidUser("username", "domain", "password")) { //Insert your code that runs under the security context of a specific user here. undoImpersonation(); } else { //Your impersonation failed. Therefore, include a fail-safe mechanism here. } } private bool impersonateValidUser(String userName, String domain, String password) { WindowsIdentity tempWindowsIdentity; IntPtr token = IntPtr.Zero; IntPtr tokenDuplicate = IntPtr.Zero; if(LogonUser(userName, domain, password, LOGON32_LOGON_INTERACTIVE, LOGON32_PROVIDER_DEFAULT, ref token) != 0) { if(DuplicateToken(token, 2, ref tokenDuplicate) != 0) { tempWindowsIdentity = new WindowsIdentity(tokenDuplicate); impersonationContext = tempWindowsIdentity.Impersonate(); if (impersonationContext != null) return true; else return false; } else return false; } else return false; } private void undoImpersonation() { impersonationContext.Undo(); } </script> 下面介紹ASP.NET應(yīng)用程序中使用身份模擬的一個(gè)簡單應(yīng)用,。例如有一個(gè)ASP.NET應(yīng)用程序要檢查服務(wù)器端某個(gè)文件是否存在,,相應(yīng)的程序代碼為:
bool a = File.Exists("D:\\Share\\test.txt"); 缺省情況下該ASP.NET應(yīng)用程序以ASPNET賬號(hào)運(yùn)行。為了安全起見,,ASPNET這個(gè)賬號(hào)并沒有服務(wù)器端D:\Share\這個(gè)目錄的訪問權(quán)限,。在不使用身份模擬的情況下,由于ASP.NET應(yīng)用程序不具有訪問該目錄的權(quán)限,,無論文件是否存在,,F(xiàn)ile.Exists的返回值將永遠(yuǎn)是false。為了解決這個(gè)問題,,可以另建一個(gè)用戶賬號(hào):FileExist,,并賦予該賬號(hào)D:\Share\目錄的訪問權(quán)限。然后在該應(yīng)用程序的Web.config文件的<identity>標(biāo)記中指定具體的用戶賬號(hào):
<identity impersonate="true" userName="FileExist" password="password" /> 來執(zhí)行該程序,。
更多信息
請(qǐng)?jiān)L問以下鏈接獲取更多信息:
1. INFO: Implementing Impersonation in an ASP.NET Application
http://support.microsoft.com/default.aspx?scid=kb;en-us;Q306158&SD=MSKB
2. INFO: ASP.NET Security Overview
http://support.microsoft.com/default.aspx?scid=kb;en-us;Q306590
3. ASP.NET Web Application Security
http://msdn.microsoft.com/library/default.asp?url=/library/en-us/cpguide/html/cpconaspnetwebapplicationsecurity.asp
|
|