.net下模拟不同身份登陆以获取不同权限
1.net下模拟不同身份登陆以获取不同权限
2
3作者:佚名 时间:2004-04-16 09:14 出处:互连网 责编:chinaitpower
4
5 摘要:.net下模拟不同身份登陆以获取不同权限
6
7
8不管是asp.net、web service还是window service,程序运行的时候只有本地计算机的部分权限,有时候需要更大的权限,比如读写某台服务器或域中的一台计算机上的文件等,这就需要更大的权限,比如域帐户权限。
9
10通过获取不同身份的WindowsImpersonationContext对象,可以模拟不同用户登陆,请看我生成的NetworkSecurity类的
11public static WindowsImpersonationContext ImpersonateUser(string strDomain,
12string strLogin,
13
14string strPwd,
15
16LogonType logonType,
17
18LogonProvider logonProvider);
19
20附NetworkSecurity.cs源代码如下:
21
22/*
23* Author : TongWei
24* Date : 2005-1-25
25* Rights : China Netwave Inc.@2005
26*/
27
28using System;
29using System.Runtime.InteropServices;
30using System.Security.Principal;
31using System.Security.Permissions;
32
33namespace CNW.OMP.Common.Utility
34{
35public enum LogonType : int
36{
37/// <summary>
38/// This logon type is intended for users who will be interactively using the computer, such as a user
39/// being logged on by a terminal server, remote shell, or similar process. This logon type has the
40/// additional expense of caching logon information for disconnected operation, and is therefore
41/// inappropriate for some client/server applications, such as a mail server.
42/// </summary>
43LOGON32_LOGON_INTERACTIVE = 2,
44
45/// <summary>
46/// This logon type is intended for high performance servers to authenticate clear text passwords.
47/// The LogonUser function does not cache credentials for this logon type.
48/// </summary>
49LOGON32_LOGON_NETWORK = 3,
50
51/// <summary>
52/// This logon type is intended for batch servers, where processes may be executing on behalf of a user
53/// without their direct intervention; or for higher performance servers that process many clear-text
54/// authentication attempts at a time, such as mail or web servers. The LogonUser function does not cache
55/// credentials for this logon type.
56/// </summary>
57LOGON32_LOGON_BATCH = 4,
58
59/// <summary>
60/// Indicates a service-type logon. The account provided must have the service privilege enabled.
61/// </summary>
62LOGON32_LOGON_SERVICE = 5,
63
64/// <summary>
65/// This logon type is intended for GINA DLLs logging on users who will be interactively using the computer.
66/// This logon type allows a unique audit record to be generated that shows when the workstation was unlocked.
67/// </summary>
68LOGON32_LOGON_UNLOCK = 7,
69
70/// <summary>
71/// Windows XP/2000: This logon type preserves the name and password in the authentication packages,
72/// allowing the server to make connections to other network servers while impersonating the client.
73/// This allows a server to accept clear text credentials from a client, call LogonUser, verify that
74/// the user can access the system across the network, and still communicate with other servers.
75/// </summary>
76LOGON32_LOGON_NETWORK_CLEARTEXT = 8,
77
78/// <summary>
79/// Windows XP/2000: This logon type allows the caller to clone its current token and specify new credentials
80/// for outbound connections. The new logon session has the same local identity, but uses different credentials
81/// for other network connections.
82/// This logon type is supported only by the LOGON32_PROVIDER_WINNT50 logon provider.
83/// </summary>
84LOGON32_LOGON_NEW_CREDENTIALS = 9
85};
86
87public enum LogonProvider : int
88{
89/// <summary>
90/// Use the standard logon provider for the system. The default security provider is NTLM.
91/// Windows XP: The default provider is negotiate, unless you pass NULL for the domain name and
92/// the user name is not in UPN format. In this case the default provider is NTLM.
93/// </summary>
94LOGON32_PROVIDER_DEFAULT = 0,
95
96/// <summary>
97/// Use the Windows NT 3.5 logon provider.
98/// </summary>
99LOGON32_PROVIDER_WINNT35 = 1,
100
101/// <summary>
102/// Use the NTLM logon provider.
103/// </summary>
104LOGON32_PROVIDER_WINNT40 = 2,
105
106/// <summary>
107/// Windows XP/2000: Use the negotiate logon provider.
108/// </summary>
109LOGON32_PROVIDER_WINNT50 = 3
110};
111
112class SecuUtil32
113{
114[DllImport("advapi32.dll", SetLastError=true)]
115public static extern bool LogonUser(String lpszUsername, String lpszDomain, String lpszPassword,
116int dwLogonType, int dwLogonProvider, ref IntPtr TokenHandle);
117
118[DllImport("kernel32.dll", CharSet=CharSet.Auto)]
119public extern static bool CloseHandle(IntPtr handle);
120
121[DllImport("advapi32.dll", CharSet=CharSet.Auto, SetLastError=true)]
122public extern static bool DuplicateToken(IntPtr ExistingTokenHandle,
123int SECURITY_IMPERSONATION_LEVEL, ref IntPtr DuplicateTokenHandle);
124}
125
126public class NetworkSecurity
127{
128public NetworkSecurity()
129{
130//
131// TODO: Add constructor logic here
132//
133}
134
135/// <summary>
136/// The ImpersonateUser function attempts to log a user on to the local computer.
137/// The local computer is the computer from which ImpersonateUser was called.
138/// You cannot use ImpersonateUser to log on to a remote computer.
139/// You specify the user with a user name and domain, and authenticate the user with a clear-text password.
140/// If the function succeeds, you receive a handle to a token that represents the logged-on user.
141/// You can then use this token handle to impersonate the specified user, or in most cases,
142/// to create a process running in the context of the specified user.
143/// </summary>
144/// <param name="strDomain">
145/// specifies the name of the domain or server whose account database contains the strLogin account.
146/// </param>
147/// <param name="strLogin">specifies the name of the user.</param>
148/// <param name="strPwd">specifies the clear-text password for the user account specified by strLogin.</param>
149/// <param name="logonType">Specifies the type of logon operation to perform.</param>
150/// <param name="logonProvider">Specifies the logon provider.</param>
151/// <example>
152/// //Add System.Security.dll
153/// //using System.Security.Principal;
154///
155/// string strDomain=ConfigurationSettings.AppSettings["mSALoginDomainName"];
156/// string strUser=ConfigurationSettings.AppSettings["mSALoginDomainUser"];
157/// string strPassword=ConfigurationSettings.AppSettings["mSALoginDomainPassword"];
158///
159/// WindowsImpersonationContext impContext = null;
160/// try
161/// {
162/// impContext = NetworkSecurity.ImpersonateUser(strDomain,strUser,strPassword,
163/// LogonType.LOGON32_LOGON_SERVICE,
164/// LogonProvider.LOGON32_PROVIDER_DEFAULT);
165/// }
166/// catch
167/// {
168///
169/// }
170///
171/// //work under this logined user
172///
173/// impContext.Undo();
174/// </example>
175/// <returns>
176/// </returns>
177public static WindowsImpersonationContext ImpersonateUser(string strDomain,
178string strLogin,
179string strPwd,
180LogonType logonType,
181LogonProvider logonProvider)
182{
183// Initialize tokens
184IntPtr tokenHandle = new IntPtr(0);
185IntPtr dupeTokenHandle = new IntPtr(0);
186tokenHandle = IntPtr.Zero;
187dupeTokenHandle = IntPtr.Zero;
188
189// If domain name was blank, assume local machine
190if (strDomain == "")
191strDomain = System.Environment.MachineName;
192
193try
194{
195const int SecurityImpersonation = 2;
196
197// Call LogonUser to obtain a handle to an access token.
198bool returnValue = SecuUtil32.LogonUser(
199strLogin,
200strDomain,
201strPwd,
202(int)logonType,
203(int)logonProvider,
204ref tokenHandle);
205
206// Did impersonation fail?
207if (false == returnValue)
208{
209int ret = Marshal.GetLastWin32Error();
210// Throw the exception show the reason why LogonUser failed
211string strErr = String.Format("LogonUser failed with error code : {0}", ret);
212throw new ApplicationException(strErr, null);
213}
214
215// Get identity before impersonation
216bool retVal = SecuUtil32.DuplicateToken(tokenHandle, SecurityImpersonation, ref dupeTokenHandle);
217
218// Did DuplicateToken fail?
219if (false == retVal)
220{
221// Close existing handle
222SecuUtil32.CloseHandle(tokenHandle);
223// Throw the exception show the reason why DuplicateToken failed
224throw new ApplicationException("Failed to duplicate token", null);
225}
226
227// Create new identity using new primary token
228// The token that is passed to the following constructor must
229// be a primary token in order to use it for impersonation.
230WindowsIdentity newId = new WindowsIdentity(dupeTokenHandle);
231WindowsImpersonationContext impersonatedUser = newId.Impersonate();
232
233return impersonatedUser;
234}
235catch (Exception ex)
236{
237throw new ApplicationException(ex.Message, ex);
238}
239finally
240{
241// Close handle
242if (tokenHandle != IntPtr.Zero)
243SecuUtil32.CloseHandle(tokenHandle);
244if (dupeTokenHandle != IntPtr.Zero)
245SecuUtil32.CloseHandle(dupeTokenHandle);
246}
247}
248}
249}
250
251
252
2
3作者:佚名 时间:2004-04-16 09:14 出处:互连网 责编:chinaitpower
4
5 摘要:.net下模拟不同身份登陆以获取不同权限
6
7
8不管是asp.net、web service还是window service,程序运行的时候只有本地计算机的部分权限,有时候需要更大的权限,比如读写某台服务器或域中的一台计算机上的文件等,这就需要更大的权限,比如域帐户权限。
9
10通过获取不同身份的WindowsImpersonationContext对象,可以模拟不同用户登陆,请看我生成的NetworkSecurity类的
11public static WindowsImpersonationContext ImpersonateUser(string strDomain,
12string strLogin,
13
14string strPwd,
15
16LogonType logonType,
17
18LogonProvider logonProvider);
19
20附NetworkSecurity.cs源代码如下:
21
22/*
23* Author : TongWei
24* Date : 2005-1-25
25* Rights : China Netwave Inc.@2005
26*/
27
28using System;
29using System.Runtime.InteropServices;
30using System.Security.Principal;
31using System.Security.Permissions;
32
33namespace CNW.OMP.Common.Utility
34{
35public enum LogonType : int
36{
37/// <summary>
38/// This logon type is intended for users who will be interactively using the computer, such as a user
39/// being logged on by a terminal server, remote shell, or similar process. This logon type has the
40/// additional expense of caching logon information for disconnected operation, and is therefore
41/// inappropriate for some client/server applications, such as a mail server.
42/// </summary>
43LOGON32_LOGON_INTERACTIVE = 2,
44
45/// <summary>
46/// This logon type is intended for high performance servers to authenticate clear text passwords.
47/// The LogonUser function does not cache credentials for this logon type.
48/// </summary>
49LOGON32_LOGON_NETWORK = 3,
50
51/// <summary>
52/// This logon type is intended for batch servers, where processes may be executing on behalf of a user
53/// without their direct intervention; or for higher performance servers that process many clear-text
54/// authentication attempts at a time, such as mail or web servers. The LogonUser function does not cache
55/// credentials for this logon type.
56/// </summary>
57LOGON32_LOGON_BATCH = 4,
58
59/// <summary>
60/// Indicates a service-type logon. The account provided must have the service privilege enabled.
61/// </summary>
62LOGON32_LOGON_SERVICE = 5,
63
64/// <summary>
65/// This logon type is intended for GINA DLLs logging on users who will be interactively using the computer.
66/// This logon type allows a unique audit record to be generated that shows when the workstation was unlocked.
67/// </summary>
68LOGON32_LOGON_UNLOCK = 7,
69
70/// <summary>
71/// Windows XP/2000: This logon type preserves the name and password in the authentication packages,
72/// allowing the server to make connections to other network servers while impersonating the client.
73/// This allows a server to accept clear text credentials from a client, call LogonUser, verify that
74/// the user can access the system across the network, and still communicate with other servers.
75/// </summary>
76LOGON32_LOGON_NETWORK_CLEARTEXT = 8,
77
78/// <summary>
79/// Windows XP/2000: This logon type allows the caller to clone its current token and specify new credentials
80/// for outbound connections. The new logon session has the same local identity, but uses different credentials
81/// for other network connections.
82/// This logon type is supported only by the LOGON32_PROVIDER_WINNT50 logon provider.
83/// </summary>
84LOGON32_LOGON_NEW_CREDENTIALS = 9
85};
86
87public enum LogonProvider : int
88{
89/// <summary>
90/// Use the standard logon provider for the system. The default security provider is NTLM.
91/// Windows XP: The default provider is negotiate, unless you pass NULL for the domain name and
92/// the user name is not in UPN format. In this case the default provider is NTLM.
93/// </summary>
94LOGON32_PROVIDER_DEFAULT = 0,
95
96/// <summary>
97/// Use the Windows NT 3.5 logon provider.
98/// </summary>
99LOGON32_PROVIDER_WINNT35 = 1,
100
101/// <summary>
102/// Use the NTLM logon provider.
103/// </summary>
104LOGON32_PROVIDER_WINNT40 = 2,
105
106/// <summary>
107/// Windows XP/2000: Use the negotiate logon provider.
108/// </summary>
109LOGON32_PROVIDER_WINNT50 = 3
110};
111
112class SecuUtil32
113{
114[DllImport("advapi32.dll", SetLastError=true)]
115public static extern bool LogonUser(String lpszUsername, String lpszDomain, String lpszPassword,
116int dwLogonType, int dwLogonProvider, ref IntPtr TokenHandle);
117
118[DllImport("kernel32.dll", CharSet=CharSet.Auto)]
119public extern static bool CloseHandle(IntPtr handle);
120
121[DllImport("advapi32.dll", CharSet=CharSet.Auto, SetLastError=true)]
122public extern static bool DuplicateToken(IntPtr ExistingTokenHandle,
123int SECURITY_IMPERSONATION_LEVEL, ref IntPtr DuplicateTokenHandle);
124}
125
126public class NetworkSecurity
127{
128public NetworkSecurity()
129{
130//
131// TODO: Add constructor logic here
132//
133}
134
135/// <summary>
136/// The ImpersonateUser function attempts to log a user on to the local computer.
137/// The local computer is the computer from which ImpersonateUser was called.
138/// You cannot use ImpersonateUser to log on to a remote computer.
139/// You specify the user with a user name and domain, and authenticate the user with a clear-text password.
140/// If the function succeeds, you receive a handle to a token that represents the logged-on user.
141/// You can then use this token handle to impersonate the specified user, or in most cases,
142/// to create a process running in the context of the specified user.
143/// </summary>
144/// <param name="strDomain">
145/// specifies the name of the domain or server whose account database contains the strLogin account.
146/// </param>
147/// <param name="strLogin">specifies the name of the user.</param>
148/// <param name="strPwd">specifies the clear-text password for the user account specified by strLogin.</param>
149/// <param name="logonType">Specifies the type of logon operation to perform.</param>
150/// <param name="logonProvider">Specifies the logon provider.</param>
151/// <example>
152/// //Add System.Security.dll
153/// //using System.Security.Principal;
154///
155/// string strDomain=ConfigurationSettings.AppSettings["mSALoginDomainName"];
156/// string strUser=ConfigurationSettings.AppSettings["mSALoginDomainUser"];
157/// string strPassword=ConfigurationSettings.AppSettings["mSALoginDomainPassword"];
158///
159/// WindowsImpersonationContext impContext = null;
160/// try
161/// {
162/// impContext = NetworkSecurity.ImpersonateUser(strDomain,strUser,strPassword,
163/// LogonType.LOGON32_LOGON_SERVICE,
164/// LogonProvider.LOGON32_PROVIDER_DEFAULT);
165/// }
166/// catch
167/// {
168///
169/// }
170///
171/// //work under this logined user
172///
173/// impContext.Undo();
174/// </example>
175/// <returns>
176/// </returns>
177public static WindowsImpersonationContext ImpersonateUser(string strDomain,
178string strLogin,
179string strPwd,
180LogonType logonType,
181LogonProvider logonProvider)
182{
183// Initialize tokens
184IntPtr tokenHandle = new IntPtr(0);
185IntPtr dupeTokenHandle = new IntPtr(0);
186tokenHandle = IntPtr.Zero;
187dupeTokenHandle = IntPtr.Zero;
188
189// If domain name was blank, assume local machine
190if (strDomain == "")
191strDomain = System.Environment.MachineName;
192
193try
194{
195const int SecurityImpersonation = 2;
196
197// Call LogonUser to obtain a handle to an access token.
198bool returnValue = SecuUtil32.LogonUser(
199strLogin,
200strDomain,
201strPwd,
202(int)logonType,
203(int)logonProvider,
204ref tokenHandle);
205
206// Did impersonation fail?
207if (false == returnValue)
208{
209int ret = Marshal.GetLastWin32Error();
210// Throw the exception show the reason why LogonUser failed
211string strErr = String.Format("LogonUser failed with error code : {0}", ret);
212throw new ApplicationException(strErr, null);
213}
214
215// Get identity before impersonation
216bool retVal = SecuUtil32.DuplicateToken(tokenHandle, SecurityImpersonation, ref dupeTokenHandle);
217
218// Did DuplicateToken fail?
219if (false == retVal)
220{
221// Close existing handle
222SecuUtil32.CloseHandle(tokenHandle);
223// Throw the exception show the reason why DuplicateToken failed
224throw new ApplicationException("Failed to duplicate token", null);
225}
226
227// Create new identity using new primary token
228// The token that is passed to the following constructor must
229// be a primary token in order to use it for impersonation.
230WindowsIdentity newId = new WindowsIdentity(dupeTokenHandle);
231WindowsImpersonationContext impersonatedUser = newId.Impersonate();
232
233return impersonatedUser;
234}
235catch (Exception ex)
236{
237throw new ApplicationException(ex.Message, ex);
238}
239finally
240{
241// Close handle
242if (tokenHandle != IntPtr.Zero)
243SecuUtil32.CloseHandle(tokenHandle);
244if (dupeTokenHandle != IntPtr.Zero)
245SecuUtil32.CloseHandle(dupeTokenHandle);
246}
247}
248}
249}
250
251
252
<%@ 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>
<%@ 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>