共用方式為


在 ASP.NET 應用程式中實作模擬

本文說明在 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 驗證的帳戶或使用者

若要模擬 Internet Information Services (IIS) 在 ASP.NET 應用程式中每個頁面的每個要求上驗證使用者,您必須在此應用程式的 Web.config 檔案中包含標記 <identity> ,並將模擬屬性設定為 true。 例如:

<identity impersonate="true" />

針對 ASP.NET 應用程式的所有要求模擬特定使用者

若要模擬 ASP.NET 應用程式所有頁面上所有要求的特定使用者,您可以在該應用程式的 Web.config 檔標記中<identity>指定 userNamepassword 屬性。 例如:

<identity impersonate="true" userName="accountname" password="password" />

注意事項

在線程上模擬特定用戶的進程身分識別,必須具有 作為操作系統許可權一部分的 Act 。 根據預設,Aspnet_wp.exe 程式會在名為 ASPNET 的電腦帳戶下執行。 不過,此帳戶沒有模擬特定使用者的必要許可權。 如果您嘗試模擬特定使用者,就會收到錯誤訊息。 此資訊僅適用於 .NET Framework 1.0。 .NET Framework 1.1 不需要此許可權。

若要解決此問題,請使用下列其中一種方法:

  • 作為操作系統一部分的 Act 許可權授與 ASPNET 帳戶, (最低許可權帳戶) 。

    注意事項

    雖然您可以使用此方法來解決此問題,但 Microsoft 不建議使用此方法。

  • 將 Aspnet_wp.exe 程式執行的帳戶變更為 Machine.config 檔案組態區段中的 <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>

如果在以 Windows 2000 為基礎的電腦上執行 Aspnet_wp.exe 進程,在線程上模擬特定使用者的進程身分識別必須具有 「作為操作系統 許可權的一部分」。 如果 Aspnet_wp.exe 程式是在 Windows XP 型電腦或 Windows Server 2003 計算機上執行,則不需要作為操作系統許可權的一部分。 根據預設,Aspnet_wp.exe 程式會在名為 ASPNET 的電腦帳戶下執行。 不過,此帳戶沒有模擬特定使用者的必要許可權。 如果您嘗試模擬特定使用者,就會收到錯誤訊息。

若要解決此問題,請使用下列其中一種方法:

  • 操作系統 許可權的一部分授與 ASPNET 帳戶。

    注意事項

    我們不建議使用此方法來解決此問題。

  • 將 Aspnet_wp.exe 程式執行的帳戶變更為 Machine.config 檔案組態區段中的 <processModel> [系統] 帳戶。

參考資料

ASP.NET 安全性概觀