У меня возникла небольшая проблема при попытке использовать класс BackgroundWorker
с олицетворением. После ответов от Google я получил этот код для олицетворения
public class MyImpersonation {
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;
}
}
Он работал очень хорошо, пока я не использовал его с классом BackgroundWorker
. В этом случае я добавил олицетворение в коде, который выполняется асинхронно. У меня нет ошибок, но проблема в том, что олицетворение не работает, когда оно используется в асинхронном методе.
В коде это выглядит примерно так:
создание экземпляра BGWorker и добавление обработчика событий в событие DoWork:
_bgWorker = new BackgroundWorker();
_bgWorker.DoWork += new DoWorkEventHandler(_bgWorker_DoWork);
в вышеприведенном обработчике выполняется олицетворение перед запуском некоторого кода.
private void _bgWorker_DoWork(object sender, DoWorkEventArgs e) {
MyImpersonation myImpersonation = new MyImpersonation();
myImpersonation.impersonateValidUser(user, domain, pass)
//run some code...
myImpersonation.undoImpersonation();
}
код запускается с
BGWorker.RunWorkerAsync();
Как я уже говорил, не выдается никакой ошибки, только то, что код действует так, как будто я не выполнял олицетворение, то есть с его учетными данными по умолчанию.
Более того, метод олицетворения возвращает true, поэтому олицетворение имело место на определенном уровне, но, вероятно, не в текущем потоке.
Это должно произойти, потому что асинхронный код выполняется в другом потоке, поэтому должно быть что-то, что нужно добавить в класс MyImpersonation
. Но что? :)