.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

<%@ 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, 2ref 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>
posted @ 2005-11-15 20:57  阿新  阅读(2100)  评论(0编辑  收藏  举报