Udostępnij za pośrednictwem


Impersonation code in C#

While investigating a customer issue, I needed code to impersonate a different user on the current thread. A quick search of the msdn blogs turned up this post, which got me most of the way there. I decided to wrap the code into a class that inherits from IDisposable just to make it easily usable in a using statement. Here is what I came up with:

using System;

using System.ComponentModel;

using System.Runtime.InteropServices;

using System.Security.Principal;

public class ImpersonatedUser : IDisposable

{

    IntPtr userHandle;

    WindowsImpersonationContext impersonationContext;

    public ImpersonatedUser(string user, string domain, string password)

    {

        userHandle = IntPtr.Zero;

        bool loggedOn = LogonUser(

            user,

            domain,

            password,

            LogonType.Interactive,

            LogonProvider.Default,

            out userHandle);

 

        if (!loggedOn)

            throw new Win32Exception(Marshal.GetLastWin32Error());

        // Begin impersonating the user

        impersonationContext = WindowsIdentity.Impersonate(userHandle);

    }

    public void Dispose()

    {

        if (userHandle != IntPtr.Zero)

        {

            CloseHandle(userHandle);

            userHandle = IntPtr.Zero;

            impersonationContext.Undo();

        }

    }

    [DllImport("advapi32.dll", SetLastError = true)]

    static extern bool LogonUser(

        string lpszUsername,

        string lpszDomain,

        string lpszPassword,

        LogonType dwLogonType,

        LogonProvider dwLogonProvider,

        out IntPtr phToken

        );

    [DllImport("kernel32.dll", SetLastError = true)]

    static extern bool CloseHandle(IntPtr hHandle);

    enum LogonType : int

    {

        Interactive = 2,

        Network = 3,

        Batch = 4,

        Service = 5,

        NetworkCleartext = 8,

        NewCredentials = 9,

    }

    enum LogonProvider : int

    {

        Default = 0,

    }

}

Comments

  • Anonymous
    September 21, 2009
    Would I be right in saying that as the ImpersonatedUser class does not have a finalizer there is no pint in calling "GC.SuppressFinalize(this);"? And there would be no point in adding a finalizer as it would run on a different thread?

  • Anonymous
    September 21, 2009
    Gareth, I believe you are right about the SuppressFinalize call.  I pounded this code out pretty quickly and didn't consider that fact.  I have removed the unnecssary code.  Thanks for the comment.