C# User Impersonation not being passed on to sub-p

2019-09-15 19:20发布

问题:

I am trying to impersonate user for all the processes running from a console app. I don't want to start my VisualStudio as that user nor want to keep attaching external process running under that user.

This is what I have tried...

       static void Main(string[] args)
        {
            Console.WriteLine("Environment.UserName: {0}", Environment.UserName); // Prints currently logged-in win username

            ConfigurationManager.GetSection("configuration");                    

            using (var impersonator = new Impersonator())
            {
                Console.WriteLine("Environment.UserName: {0}", Environment.UserName); // Prints impersonated username

                var hostAccount = new System.ServiceModel.ServiceHost(typeof(AccountService));  // WCF Service class            
                hostAccount.Open();
            }
        }

If I try to inspect value of Environment.UserName inside any method of AccountService class, it always gives me currently logged-in win username instead of impersonated user.

My Impersonator class uses following code to impersonate user.

bool returnValue = LogonUser(user, userDomain, password, LOGON32_LOGON_INTERACTIVE, LOGON32_PROVIDER_DEFAULT, ref _userHandle);

if (!returnValue)
    throw new ApplicationException("Could not impersonate user");

WindowsIdentity newId = new WindowsIdentity(_userHandle);
_impersonatedUser = newId.Impersonate();

I am trying to achieve something what the following code does but running app in debug mode and without changing any current wcf config.

Process.Start("path to exe", "user", ssPwd, "MyDOMAIN");

I do understand there is difference between running the whole app as an user and impersonating an user inside app. But just want to see if someone had similar issue and managed to find a solution.

Edit 1:

I have tried starting new threads after impersonating a user and they all were running under impersonated user. So new threads do get impersonated context. I guess it has something to do with how wcf host gets started.

回答1:

wcfhost.open() always runs under main user identity and not under impersonated identity. So now I am starting my main console app under different user from another console app and attaching debugger to it and it works.

I have copied my code below if it helps anyone.

using System;
using System.Linq;
using System.Runtime.InteropServices;
using System.Security;
using EnvDTE80;
using Process = System.Diagnostics.Process;

namespace StartService
{
    class Program
    {
        static void Main(string[] args)
        {
            var secure = new SecureString();
            foreach (var c in "password-from-config")
            {
                secure.AppendChar(c);
            }

            Process process = null;

            try
            {
                process = Process.Start(@"C:\Test Projects\WcfServiceTest\WcfServiceTest\bin\Debug\WcfServiceTest.exe",
                    "TestUser", secure, "DomainName");

                Attach(GetCurrent());

                Console.ReadKey();
            }
            finally
            {
                if (process != null && !process.HasExited)
                {
                    process.CloseMainWindow();
                    process.Close();
                }    
            }
        }

        public static void Attach(DTE2 dte)
        {
            var processes = dte.Debugger.LocalProcesses;
            foreach (var proc in processes.Cast<EnvDTE.Process>().Where(proc => proc.Name.IndexOf("WcfServiceTest.exe") != -1))
                proc.Attach();
        }

        internal static DTE2 GetCurrent()
        {
            var dte2 = (DTE2)Marshal.GetActiveObject("VisualStudio.DTE.12.0"); // Specific to VS2013

            return dte2;
        }
    }
}