олицетворение и BackgroundWorker - PullRequest
2 голосов
/ 08 апреля 2009

У меня возникла небольшая проблема при попытке использовать класс 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. Но что? :)

1 Ответ

0 голосов
/ 22 июня 2009

У меня такая же проблема. У меня есть фоновый работник, который олицетворяет статический класс в событии DoWork. Я пытаюсь выдать себя за другого пользователя Active Domain, чтобы прочитать каталог, к которому у основного пользователя нет доступа. Если я запускаю приложение в IDE, олицетворенный пользователь может читать файлы без проблем. Если я запускаю приложение из файловой системы, олицетворение все равно происходит, но возникает исключение, говорящее, что у олицетворенного пользователя нет доступа.

Из того, что я прочитал, связано с настройкой Assembly: SecurityPermissionAttribute и Assembly: PermissionSetAttribute.

Перед объявлением класса у меня есть следующее:

    <Assembly: SecurityPermissionAttribute(SecurityAction.RequestMinimum, UnmanagedCode:=True), _
Assembly: PermissionSetAttribute(SecurityAction.RequestMinimum, Name:="FullTrust")> 

Перед моей функцией StartImpersonating () у меня есть:

<PermissionSetAttribute(SecurityAction.Demand, Name:="FullTrust")> _

Однако я работаю с VB.NET, а не с C #.

...