本文說明在 ASP.NET 應用程式中實作仿真的不同方式。
原始產品版本: ASP.NET
原始 KB 編號: 306158
摘要
本文介紹如何藉由修改 Web.config 檔案和執行特定程式代碼區段來實作模擬。
它指的是下列Microsoft .NET Framework 類別庫命名空間:
System.Web.Security
System.Security.Principal
System.Runtime.InteropServices
您可以使用下列程式代碼來判斷線程執行身分的使用者:
System.Security.Principal.WindowsIdentity.GetCurrent().Name
模擬 IIS 驗證的帳戶或使用者
若要在 ASP.NET 應用程式中每個頁面的每個要求上模擬 網際網路資訊服務 (IIS)驗證使用者,您必須在此<identity>
應用程式的Web.config 檔案中包含標記,並將模擬屬性設定為 true。 例如:
<identity impersonate="true" />
針對 ASP.NET 應用程式的所有要求模擬特定使用者
若要模擬 ASP.NET 應用程式所有頁面上所有要求的特定使用者,您可以在該應用程式的 Web.config 檔案標記中<identity>
指定 userName
和 password
屬性。 例如:
<identity impersonate="true" userName="<accountName>" password="<credentialPlaceholder>"/>
注意
模擬線程上特定使用者之進程的身分識別,必須具有 作為作系統 許可權一部分的 Act。 根據預設,Aspnet_wp.exe進程會在名為 ASPNET 的電腦帳戶下執行。 不過,此帳戶沒有模擬特定使用者的必要許可權。 如果您嘗試模擬特定使用者,您會收到錯誤訊息。 此資訊僅適用於 .NET Framework 1.0。 .NET Framework 1.1 不需要此許可權。
若要解決此問題,請使用下列其中一種方法:
將 Act 作為作系統許可權的一部分授與 ASPNET 帳戶(最低特殊許可權帳戶)。
注意
雖然您可以使用此方法解決此問題,但Microsoft不建議使用此方法。
在 Machine.config 檔案的組態區段中,將Aspnet_wp.exe進程執行的帳戶變更為 [系統帳戶
<processModel>
]。
在程式代碼中模擬驗證使用者
若要只在您執行特定程式碼區段時模擬驗證使用者 (User.Identity
),您可以使用程式代碼來追蹤。 此方法要求驗證使用者身分識別的類型為 WindowsIdentity
。
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();
在程式代碼中模擬特定使用者
若要只在您執行特定程式代碼區段時模擬特定使用者,請使用下列程式代碼:
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 Function LogonUserA 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, _
ByVal ImpersonationLevel As Integer, _
ByRef DuplicateTokenHandle As IntPtr) As Integer
Declare Auto Function RevertToSelf Lib "advapi32.dll" () As Long
Declare Auto Function CloseHandle Lib "kernel32.dll" (ByVal handle As IntPtr) As Long
Public Sub Page_Load(ByVal s As Object, ByVal 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(ByVal userName As String, _
ByVal domain As String, ByVal password As String) As Boolean
Dim tempWindowsIdentity As WindowsIdentity
Dim token As IntPtr = IntPtr.Zero
Dim tokenDuplicate As IntPtr = IntPtr.Zero
impersonateValidUser = False
If RevertToSelf() Then
If LogonUserA(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 Not impersonationContext Is Nothing Then
impersonateValidUser = True
End If
End If
End If
End If
If Not tokenDuplicate.Equals(IntPtr.Zero) Then
CloseHandle(tokenDuplicate)
End If
If Not token.Equals(IntPtr.Zero) Then
CloseHandle(token)
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")]
public static extern int LogonUserA(String lpszUserName,
String lpszDomain,
String lpszPassword,
int dwLogonType,
int dwLogonProvider,
ref IntPtr phToken);
[DllImport("advapi32.dll", CharSet=CharSet.Auto, SetLastError=true)]
public static extern int DuplicateToken(IntPtr hToken,
int impersonationLevel,
ref IntPtr hNewToken);
[DllImport("advapi32.dll", CharSet=CharSet.Auto, SetLastError=true)]
public static extern bool RevertToSelf();
[DllImport("kernel32.dll", CharSet=CharSet.Auto)]
public static extern bool CloseHandle(IntPtr handle);
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(RevertToSelf())
{
if(LogonUserA(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)
{
CloseHandle(token);
CloseHandle(tokenDuplicate);
return true;
}
}
}
}
if(token!= IntPtr.Zero)
CloseHandle(token);
if(tokenDuplicate!=IntPtr.Zero)
CloseHandle(tokenDuplicate);
return false;
}
private void undoImpersonation()
{
impersonationContext.Undo();
}
</script>
模擬線程上特定使用者之進程的身分識別,如果Aspnet_wp.exe進程是在 Windows 2000 型電腦上執行,則必須具有 作為作系統 許可權的一部分。 如果Aspnet_wp.exe進程是在 Windows XP 型電腦上或在 Windows Server 2003 型電腦上執行,則不需要作為作系統許可權的一部分。 根據預設,Aspnet_wp.exe進程會在名為 ASPNET 的電腦帳戶下執行。 不過,此帳戶沒有模擬特定使用者的必要許可權。 如果您嘗試模擬特定使用者,您會收到錯誤訊息。
若要解決此問題,請使用下列其中一種方法:
將 Act 作為作系統許可權的一部分授與 ASPNET 帳戶。
注意
我們不建議您使用此方法來解決此問題。
在 Machine.config 檔案的組態區段中,將Aspnet_wp.exe進程執行的帳戶變更為 [系統帳戶
<processModel>
]。