2

I have a little bit of a problem when trying to use the BackgroundWorker class with impersonation. Following the answers from Google, I got this code to impersonate

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;
    }
}

It worked really well until I used it with the BackgroundWorker class. In this case, I've added a impersonation in the the code that runs asynchronously. I have no errors, but the issue I'm having is that the impersonation does not work when it is used in the async method.

In code this looks something like this:

  • instantiate a BGWorker, and add an event handler to the DoWork event:

    _bgWorker = new BackgroundWorker();
    _bgWorker.DoWork += new DoWorkEventHandler(_bgWorker_DoWork);
    
  • in the above handler, a impersonation is made before running some code.

    private void _bgWorker_DoWork(object sender, DoWorkEventArgs e) {        
            MyImpersonation myImpersonation = new MyImpersonation();
            myImpersonation.impersonateValidUser(user, domain, pass)        
           //run some code...        
           myImpersonation.undoImpersonation();        
    }
    
  • the code is launched with

    BGWorker.RunWorkerAsync();
    

As I said before, no error is thrown, only that the code acts as if I didn't run any impersonation, that is with its default credentials.

Moreover, the impersonation method returns true, so the impersonation took place at a certain level, but probably not on the current thread.

This must happen because the async code runs on another thread, so there must be something that needs to be added to the MyImpersonation class. But what? :)

4

1 回答 1

0

我也有同样的问题。我有一个后台工作人员在 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#。

-D

于 2009-06-22T13:46:11.380 回答