Impersonate Logon Windows


//Sample 1: WindowsImpersonationContext.cs
using System.Security.Principal;
using System.Security.Permissions;
[
    assembly: SecurityPermissionAttribute
                                (
                                    SecurityAction.RequestMinimum,
                                    UnmanagedCode=true
                                )
]
[
    assembly: PermissionSetAttribute
                                (
                                    SecurityAction.RequestMinimum,
                                    Name = "FullTrust"
                                )
]
namespace Microshaoft
{
    // This sample demonstrates the use of the WindowsIdentity class to impersonate a user.
    // IMPORTANT NOTES: 
    // This sample can be run only on Windows XP.  The default Windows 2000 security policy 
    // prevents this sample from executing properly, and changing the policy to allow
    // proper execution presents a security risk. 
    // This sample requests the user to enter a password on the console screen.
    // Because the console window does not support methods allowing the password to be masked, 
    // it will be visible to anyone viewing the screen.
    // The sample is intended to be executed in a .NET Framework 1.1 environment.  To execute
    // this code in a 1.0 environment you will need to use a duplicate token in the call to the
    // WindowsIdentity constructor. See KB article Q319615 for more information.
    using System;
    using System.Runtime.InteropServices;
    using Microshaoft;
    public class ImpersonationDemo
    {
        [
            DllImport
                    (
                        "advapi32.dll",
                        SetLastError = true
                    )
        ]
        public static extern bool LogonUser
                                        (
                                            string lpszUsername,
                                            string lpszDomain,
                                            string lpszPassword,
                                            int dwLogonType,
                                            int dwLogonProvider,
                                            ref IntPtr phToken
                                        );
        [
            DllImport
                    (
                        "kernel32.dll",
                        CharSet =  CharSet.Auto
                    )
        ]
        private static extern int FormatMessage
                                            (
                                                int dwFlags,
                                                ref IntPtr lpSource,
                                                int dwMessageId,
                                                int dwLanguageId,
                                                ref string lpBuffer,
                                                int nSize,
                                                IntPtr args
                                            );
        [
            DllImport
                    (
                        "kernel32.dll",
                        CharSet = CharSet.Auto
                    )
        ]
        public extern static bool CloseHandle(IntPtr handle);
        [
            DllImport
                    (
                        "advapi32.dll",
                        CharSet = CharSet.Auto,
                        SetLastError = true
                    )
        ]
        public extern static bool DuplicateToken
                                            (
                                                IntPtr ExistingTokenHandle,
                                                int SECURITY_IMPERSONATION_LEVEL,
                                                ref IntPtr DuplicateTokenHandle
                                            );
        // Test harness.
        // If you incorporate this code into a DLL, be sure to demand FullTrust.
        [
            PermissionSetAttribute
                            (
                                SecurityAction.Demand,
                                Name = "FullTrust"
                            )
        ]
        public static void Main(string[] args)
        {    
            IntPtr tokenHandle = new IntPtr(0);
            IntPtr dupeTokenHandle = new IntPtr(0);
            try
            {
                string userName, domainName;
                // Get the user token for the specified user, domain, and password using the 
                // unmanaged LogonUser method.  
                // The local machine name can be used for the domain name to impersonate a user on this machine.
                Console.WriteLine("Enter the name of the domain on which to log on: ");
                domainName = Console.ReadLine();
                Console.WriteLine("Enter the login of a user on {0} that you wish to impersonate: ", domainName);
                userName = Console.ReadLine();
                Console.WriteLine("Enter the password for {0}: ", userName);
                
                const int LOGON32_PROVIDER_DEFAULT = 0;
                //This parameter causes LogonUser to create a primary token.
                const int LOGON32_LOGON_INTERACTIVE = 2;
                tokenHandle = IntPtr.Zero;
                string password;
                password = ConsoleHelper.ReadMaskLine('*', true);
                // Call LogonUser to obtain a handle to an access token.
                bool returnValue = LogonUser
                                        (
                                            userName,
                                            domainName,
                                            password,
                                            LOGON32_LOGON_INTERACTIVE,
                                            LOGON32_PROVIDER_DEFAULT,
                                            ref tokenHandle
                                        );
                Console.WriteLine("LogonUser called.");
                if (false == returnValue)
                {
                    int ret = Marshal.GetLastWin32Error();
                    Console.WriteLine("LogonUser failed with error code : {0}", ret);
                    throw new System.ComponentModel.Win32Exception(ret);
                }
                Console.WriteLine("Did LogonUser Succeed? " + (returnValue? "Yes" : "No"));
                Console.WriteLine("Value of Windows NT token: " + tokenHandle);
                // Check the identity.
                Console.WriteLine("Before impersonation: "
                    + WindowsIdentity.GetCurrent().Name);
                // Use the token handle returned by LogonUser.
                WindowsIdentity newId = new WindowsIdentity(tokenHandle);
                WindowsImpersonationContext impersonatedUser = newId.Impersonate();
                // Check the identity.
                Console.WriteLine("After impersonation: "
                    + WindowsIdentity.GetCurrent().Name);
                // Stop impersonating the user.
                impersonatedUser.Undo();
                // Check the identity.
                Console.WriteLine("After Undo: " + WindowsIdentity.GetCurrent().Name);
                // Free the tokens.
                if (tokenHandle != IntPtr.Zero)
                {
                    CloseHandle(tokenHandle);
                }
            }
            catch(Exception ex)
            {
                Console.WriteLine("Exception occurred. " + ex.Message);
            }
        }
    }
}
namespace Microshaoft
{
    using System;
    public class ConsoleHelper
    {
        public static string ReadMaskLine
            (
                char PasswordChar
                , bool WithMask
            )
        {
            string password = "";
            ConsoleKey ck;
            string s = @"~!@#$%&*()_+`1234567890-="; //可输入字符
            s += @"QWERTYUIOP{}|qwertyuiop[]\";
            s += "ASDFGHJKL:\"asdfghjkl;'";
            s += "ZXCVBNM<>?zxcvbnm,./ ";
            do
            {
                ConsoleKeyInfo cki = Console.ReadKey(true);
                char c = cki.KeyChar;
                ck = cki.Key;
                int p = Console.CursorLeft;
                if (ck == ConsoleKey.Backspace)
                {
                    string left = "";
                    if (p > 0)
                    {
                        left = password.Substring(0, p - 1);
                    }
                    string right = password.Substring(p);
                    password  = left + right;
                    Console.Write(c);
                    string output = right;
                    if (WithMask)
                    {
                        output = GetPasswordChars(right, PasswordChar);
                    }
                    output += "\0";
                    Console.Write(output);
                    if (p > 0)
                    {
                        p --;
                    }
                }
                else if (ck == ConsoleKey.Delete)
                {
                    string left = "";
                    if (p > 0)
                    {
                        left = password.Substring(0, p);
                    }
                    string right = "";
                    if (p < password.Length)
                    {
                        right = password.Substring(p + 1);
                    }
                    password = left + right;
                    //Console.Write(right + " ");
                    string output = right;
                    if (WithMask)
                    {
                        output = GetPasswordChars(right, PasswordChar);
                    }
                    output += "\0";
                    Console.Write(output);
                }
                else
                {
                    if (s.IndexOf(c) >= 0)
                    {
                        string left = password.Substring(0, p);
                        string right = password.Substring(p);
                        password = left + c + right;
                        string output = c + right;
                        if (WithMask)
                        {
                            output = GetPasswordChars(c + right, PasswordChar);
                        }
                        Console.Write(output);
                        p ++;
                    }
                    else
                    {
                        switch (ck)
                        {
                            case ConsoleKey.LeftArrow :
                                if (p > 0)
                                {
                                    p --;
                                }
                                break;
                            case ConsoleKey.RightArrow :
                                if (p < password.Length)
                                {
                                    p ++;
                                }
                                break;
                            case ConsoleKey.Home :
                                p = 0;
                                break;
                            case ConsoleKey.End :
                                p = password.Length;
                                break;
                            default :
                                Console.Beep();
                                break;
                        }
                    }
                }
                Console.CursorLeft = p;
            } while (ck != ConsoleKey.Enter);
            //Console.WriteLine("[" + password + "]");
            return password;
        }
        private static string GetPasswordChars(string s, char c)
        {
            string passwordChars = "";
            for (int i = 0; i < s.Length; i++)
            {
                passwordChars += c;
            }
            return passwordChars;
        }
    }
}


//Sample2.cs
namespace TestApplication
{
    using System;
    using System.Security.Principal;
    using Microshaoft.Win32;
    using Microshaoft;
    public class Class1
    {
        /// <summary>
        /// 应用程序的主入口点。
        /// </summary>
        //[STAThread]
        static void Main(string[] args)
        {
            Console.WriteLine(WindowsIdentity.GetCurrent().Name);
            Console.WriteLine("pls input your username:");
            string user;
            user = Console.ReadLine();
            Console.WriteLine("pls input your password:");
            string password;
            password = ConsoleHelper.ReadMaskLine('*', true);
            Console.WriteLine();
            Console.WriteLine("pls input your domain:");
            string domain;
            domain = Console.ReadLine();
            LogonImpersonate x = new LogonImpersonate
                                            (
                                                user
                                                , password
                                                , domain
                                            );
            Console.WriteLine("Hello {0}", WindowsIdentity.GetCurrent().Name);
        }
    }
}
namespace Microshaoft
{
    using System;
    public class ConsoleHelper
    {
        public static string ReadMaskLine
            (
                char PasswordChar
                , bool WithMask
            )
        {
            string password = "";
            ConsoleKey ck;
            string s = @"~!@#$%&*()_+`1234567890-="; //可输入字符
            s += @"QWERTYUIOP{}|qwertyuiop[]\";
            s += "ASDFGHJKL:\"asdfghjkl;'";
            s += "ZXCVBNM<>?zxcvbnm,./ ";
            do
            {
                ConsoleKeyInfo cki = Console.ReadKey(true);
                char c = cki.KeyChar;
                ck = cki.Key;
                int p = Console.CursorLeft;
                if (ck == ConsoleKey.Backspace)
                {
                    string left = "";
                    if (p > 0)
                    {
                        left = password.Substring(0, p - 1);
                    }
                    string right = password.Substring(p);
                    password  = left + right;
                    Console.Write(c);
                    string output = right;
                    if (WithMask)
                    {
                        output = GetPasswordChars(right, PasswordChar);
                    }
                    output += "\0";
                    Console.Write(output);
                    if (p > 0)
                    {
                        p --;
                    }
                }
                else if (ck == ConsoleKey.Delete)
                {
                    string left = "";
                    if (p > 0)
                    {
                        left = password.Substring(0, p);
                    }
                    string right = "";
                    if (p < password.Length)
                    {
                        right = password.Substring(p + 1);
                    }
                    password = left + right;
                    //Console.Write(right + " ");
                    string output = right;
                    if (WithMask)
                    {
                        output = GetPasswordChars(right, PasswordChar);
                    }
                    output += "\0";
                    Console.Write(output);
                }
                else
                {
                    if (s.IndexOf(c) >= 0)
                    {
                        string left = password.Substring(0, p);
                        string right = password.Substring(p);
                        password = left + c + right;
                        string output = c + right;
                        if (WithMask)
                        {
                            output = GetPasswordChars(c + right, PasswordChar);
                        }
                        Console.Write(output);
                        p ++;
                    }
                    else
                    {
                        switch (ck)
                        {
                            case ConsoleKey.LeftArrow :
                                if (p > 0)
                                {
                                    p --;
                                }
                                break;
                            case ConsoleKey.RightArrow :
                                if (p < password.Length)
                                {
                                    p ++;
                                }
                                break;
                            case ConsoleKey.Home :
                                p = 0;
                                break;
                            case ConsoleKey.End :
                                p = password.Length;
                                break;
                            default :
                                Console.Beep();
                                break;
                        }
                    }
                }
                Console.CursorLeft = p;
            } while (ck != ConsoleKey.Enter);
            //Console.WriteLine("[" + password + "]");
            return password;
        }
        private static string GetPasswordChars(string s, char c)
        {
            string passwordChars = "";
            for (int i = 0; i < s.Length; i++)
            {
                passwordChars += c;
            }
            return passwordChars;
        }
    
    }
}
namespace Microshaoft.Win32
{
    using System;
    using System.Runtime.InteropServices;
    using System.Security.Principal;
    public class LogonImpersonate : IDisposable
    {
        static public string DefaultDomain
        {
            get
            {
                return ".";
            }
        }
        #region DynamicInvoke
        static public object DynamicInvoke
            (
                string username
                , string password
                , Delegate handler
                , object[] args
            )
        {
            if(handler == null)
            {
                throw(new ArgumentNullException("handler"));
            }
            using(new LogonImpersonate(username,password))
            {
                return handler.DynamicInvoke(args);
            }
        }
        static public object DynamicInvoke
            (
                string username
                , string password
                , string domain
                , Delegate handler
                , object[] args
            )
        {
            if(handler == null)
            {
                throw(new ArgumentNullException("handler"));
            }
            using(new LogonImpersonate(username,password,domain))
            {
                return handler.DynamicInvoke(args);
            }
        }
        static public void DynamicInvoke(string username,string password,EventHandler handler,object sender,EventArgs e)
        {
            if(handler == null)
            {
                throw(new ArgumentNullException("handler"));
            }
            using(new LogonImpersonate(username,password))
            {
                handler(sender,e);
            }
        }
        static public void DynamicInvoke
            (
                string username
                , string password
                , string domain
                , EventHandler handler
                , object sender
                , EventArgs e
            )
        {
            if(handler == null)
            {
                throw(new ArgumentNullException("handler"));
            }
            using(new LogonImpersonate(username,password,domain))
            {
                handler(sender, e);
            }
        }
        #endregion
        #region PInvoke
        const int LOGON32_LOGON_INTERACTIVE=2;
        const int LOGON32_PROVIDER_DEFAULT=0;
        [DllImport("Kernel32.dll")]
        extern static int FormatMessage
            (
                int flag
                , ref IntPtr source
                , int msgid
                , int langid
                , ref string buf
                ,int size
                , ref IntPtr args
            );
        [DllImport("Kernel32.dll")]
        extern static bool CloseHandle(IntPtr handle);
        [DllImport("Advapi32.dll",SetLastError=true)]
        extern static bool LogonUser
            (
                string lpszUsername
                , string lpszDomain
                , string lpszPassword
                , int dwLogonType
                , int dwLogonProvider
                , ref IntPtr phToken
            );
        #endregion
        IntPtr token;
        WindowsImpersonationContext context;
        public LogonImpersonate(string username,string password)
        {
            if(username == null)
            {
                throw(new ArgumentNullException("username"));
            }
            if (password == null)
            {
                throw(new ArgumentNullException("password"));
            }
            if(username.IndexOf("\\") == -1)
            {
                Init(username, password, DefaultDomain);
            }
            else
            {
                string[] pair = username.Split(new char[]{'\\'},2);
                Init(pair[1],password,pair[0]);
            }
        }
        public LogonImpersonate(string username,string password,string domain)
        {
            if (username == null) throw (new ArgumentNullException("username"));
            if (password == null) throw (new ArgumentNullException("password"));
            if (domain == null) throw(new ArgumentNullException("domain"));
            Init(username, password, domain);
        }
        void Init
            (
                string username
                , string password
                , string domain
            )
        {
            if (
                    LogonUser
                        (
                            username
                            , domain
                            , password
                            , LOGON32_LOGON_INTERACTIVE
                            , LOGON32_PROVIDER_DEFAULT
                            , ref token
                        )
                )
            {
                bool error=true;
                try
                {
                    context = WindowsIdentity.Impersonate(token);
                    error = false;
                }
                finally
                {
                    if(error)
                    {
                        CloseHandle(token);
                    }
                }
            }
            else
            {
                int err = Marshal.GetLastWin32Error();
            
                IntPtr tempptr = IntPtr.Zero;
                string msg = null;
                FormatMessage
                        (
                            0x1300
                            , ref tempptr
                            , err
                            , 0
                            , ref msg
                            , 255
                            , ref tempptr
                        );
                throw(new Exception(msg));
            }
        }
        ~LogonImpersonate()
        {
            Dispose();
        }
        public void Dispose()
        {
            if (context != null)
            {
                try
                {
                    context.Undo();
                }
                finally
                {
                    CloseHandle(token);
                    context=null;
                }
            }
        }
    }
}

原文地址:https://www.cnblogs.com/Microshaoft/p/1378364.html