Sometimes it is necessary to change the user under whose account asp.net runs to execute a special method. This could be the case e.g. if you want to access an ADS with a local asp.net user and you get an error message "invalid username or password" (there is the possibility to pass a username and passwort, but that didn't work for me).
The usage of the class below is very simple:
...
Impersonation imp = new Impersonation();
imp.ImpersonateValidUser("username", "domain", "password");
//execute your work here
imp.UndoImpersonation();
....
using System;
using System.Security.Principal;
using System.Runtime.InteropServices;
namespace Security
{
public class Impersonation
{
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 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;
}
public void UndoImpersonation()
{
impersonationContext.Undo();
}
}
}