前言
在实际的项目开发中,我们可能会需要调用一些非托管程序,而有些非托管程序需要有更高的身份权限才能正确执行。本文介绍了如何让IIS承载的ASP.NET网站以特定的账户执行,比如Administrator。
概要
本文介绍了在 ASP.NET 应用程序中实现模拟用户身份的不同方式。
更多信息
如果要在 ASP.NET 中的线程上模拟用户,可以根据您的要求使用以下方法之一:
- 模拟 IIS 验证的帐户或用户
- 为 ASP.NET 应用程序的所有请求模拟特定用户
- 在代码中模拟身份验证用户
- 在代码中模拟特定用户
注意:可以使用以下代码来确定线程作为哪个用户执行:
System.Security.Principal.WindowsIdentity.GetCurrent().Name
模拟 IIS 验证的帐户或用户
若要在收到 ASP.NET 应用程序中每个页的每个请求时模拟 Microsoft Internet 信息服务 (IIS) 身份验证用户,必须在此应用程序的 Web.config 文件中包含 <identity> 标记,并将 impersonate 属性设置为 true。例如:
<identity impersonate="true" />
为 ASP.NET 应用程序的所有请求模拟特定用户
若要为 ASP.NET 应用程序的所有页面上的所有请求模拟特定用户,可以在该应用程序的 Web.config 文件的 <identity> 标记中指定 userName 和 password 属性。例如:
<identity impersonate="true" userName="accountname" password="password" />
在代码中模拟身份验证用户
若要仅在运行代码的特定部分时模拟身份验证用户 (User.Identity),您可以使用以下代码。此方法要求身份验证用户标识的类型为 WindowsIdentity。
Visual Basic .NET
Dim impersonationContext As System.Security.Principal.WindowsImpersonationContext Dim currentWindowsIdentity As System.Security.Principal.WindowsIdentitycurrentWindowsIdentity = 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 J# .NET
System.Security.Principal.WindowsImpersonationContext impersonationContext; impersonationContext = ((System.Security.Principal.WindowsIdentity)get_User().get_Identity()).Impersonate();//Insert your code that runs under the security context of the authenticating user here. impersonationContext.Undo();
在代码中模拟特定用户
若要仅在运行代码的特定部分时模拟特定用户,请使用以下代码:
<%@ 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 = 0Dim impersonationContext As WindowsImpersonationContextDeclare 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 IntegerDeclare Auto Function DuplicateToken Lib "advapi32.dll" ( _ByVal ExistingTokenHandle As IntPtr, _ByVal ImpersonationLevel As Integer, _ByRef DuplicateTokenHandle As IntPtr) As IntegerDeclare Auto Function RevertToSelf Lib "advapi32.dll" () As Long Declare Auto Function CloseHandle Lib "kernel32.dll" (ByVal handle As IntPtr) As LongPublic 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 SubPrivate Function impersonateValidUser(ByVal userName As String, _ ByVal domain As String, ByVal password As String) As BooleanDim tempWindowsIdentity As WindowsIdentityDim token As IntPtr = IntPtr.ZeroDim tokenDuplicate As IntPtr = IntPtr.ZeroimpersonateValidUser = FalseIf RevertToSelf() ThenIf LogonUserA(userName, domain, password, LOGON32_LOGON_INTERACTIVE, LOGON32_PROVIDER_DEFAULT, token) <> 0 ThenIf DuplicateToken(token, 2, tokenDuplicate) <> 0 ThentempWindowsIdentity = New WindowsIdentity(tokenDuplicate)impersonationContext = tempWindowsIdentity.Impersonate()If Not impersonationContext Is Nothing ThenimpersonateValidUser = TrueEnd IfEnd IfEnd IfEnd IfIf Not tokenDuplicate.Equals(IntPtr.Zero) ThenCloseHandle(tokenDuplicate)End IfIf Not token.Equals(IntPtr.Zero) ThenCloseHandle(token)End If End FunctionPrivate Sub undoImpersonation()impersonationContext.Undo() End Sub </script>
<%@ 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>
<%@ Page language="VJ#" %> <%@ Import Namespace="System.Web" %> <%@ Import Namespace="System.Web.Security" %> <%@ Import Namespace="System.Security.Principal" %> <%@ Import Namespace="System.Runtime.InteropServices" %><script runat=server> public static int LOGON32_LOGON_INTERACTIVE = 2; public static int LOGON32_PROVIDER_DEFAULT = 0;WindowsImpersonationContext impersonationContext; /** @attribute DllImport("advapi32.dll") */ public static native int LogonUserA(String lpszUserName, String lpszDomain, String lpszPassword,int dwLogonType, int dwLogonProvider, System.IntPtr[] phToken);/** @attribute DllImport("advapi32.dll",CharSet=CharSet.Auto, SetLastError=true) */ public static native int DuplicateToken(System.IntPtr hToken,int impersonationLevel,System.IntPtr[] hNewToken);/** @attribute DllImport("kernel32.dll",CharSet=CharSet.Auto) */ public static native boolean CloseHandle(System.IntPtr[] handle);/** @attribute DllImport("advapi32.dll",CharSet=CharSet.Auto,SetLastError=true) */ public static native boolean RevertToSelf();public void Page_Load(Object s, System.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 boolean impersonateValidUser(String userName, String domain, String password) {WindowsIdentity tempWindowsIdentity;System.IntPtr[] token = new System.IntPtr[1];System.IntPtr[] tokenDuplicate = new System.IntPtr[1];if(RevertToSelf()){if(LogonUserA(userName, domain, password, LOGON32_LOGON_INTERACTIVE, LOGON32_PROVIDER_DEFAULT, token) != 0){if(DuplicateToken(token[0], 2, tokenDuplicate) != 0) {tempWindowsIdentity = new WindowsIdentity(tokenDuplicate[0]);impersonationContext = tempWindowsIdentity.Impersonate();if (impersonationContext != null){CloseHandle(tokenDuplicate);CloseHandle(token);return true;} } } }if(!token[0].Equals(System.IntPtr.Zero))CloseHandle(token);if(!tokenDuplicate[0].Equals(System.IntPtr.Zero))CloseHandle(tokenDuplicate);return false;}private void undoImpersonation() {impersonationContext.Undo(); } </script>