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 (2)

  1. Gareth says:

    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?

  2. joncole says:

    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.