。Net核心模拟不适用于Process.Start

问题描述 投票:2回答:3

。Net Core下使用模拟时,我似乎无法以其他用户身份启动进程。我在以用户1运行的Linqpad中运行此脚本,并尝试以用户2启动程序。最初,模拟似乎可以正常工作(在RunImpersonated方法中,当前用户的Console.Writelines从User1正确更改为User2)。但是,该进程始终以User1身份运行。

[这是我为了验证RunImpersonated是否有效而进行的许多测试之一(最初的原因是ASP.Net Core App试图模拟当前用户的问题)。这是我能找到的最简单的可复制示例。

[DllImport("advapi32.dll", SetLastError = true, CharSet = CharSet.Unicode)]
public static extern bool LogonUser(String lpszUsername, String lpszDomain, String lpszPassword,
    int dwLogonType, int dwLogonProvider, out SafeAccessTokenHandle phToken);

void Main()
{
    string domainName = "myDomain";
    string userName = "User2";
    string passWord = "User2Password";

    const int LOGON32_PROVIDER_DEFAULT = 0;
    //This parameter causes LogonUser to create a primary token. 
    const int LOGON32_LOGON_INTERACTIVE = 2;

    // Call LogonUser to obtain a handle to an access token. 
    SafeAccessTokenHandle safeAccessTokenHandle;
    bool returnValue = LogonUser(userName, domainName, passWord,
        LOGON32_LOGON_INTERACTIVE, LOGON32_PROVIDER_DEFAULT,
        out safeAccessTokenHandle);

    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"));
    // Check the identity.
    Console.WriteLine("Before impersonation: " + WindowsIdentity.GetCurrent().Name);

    // Note: if you want to run as unimpersonated, pass
    //       'SafeAccessTokenHandle.InvalidHandle' instead of variable 'safeAccessTokenHandle'
    WindowsIdentity.RunImpersonated(
        safeAccessTokenHandle,
        // User action
        () =>
        {
            // Check the identity.
            Console.WriteLine("During impersonation: " + WindowsIdentity.GetCurrent().Name);
            Directory.GetFiles(@"C:\TMP\").Dump();
            var pi = new ProcessStartInfo
            {
                WorkingDirectory = @"C:\TMP\",
                FileName = @"C:\TMP\TestUser.exe"
            };
            var proc = Process.Start(pi);
            proc.WaitForExit();
        }
        );

    // Check the identity again.
    Console.WriteLine("After impersonation: " + WindowsIdentity.GetCurrent().Name);
}
c# asp.net-core .net-core impersonation windows-identity
3个回答
1
投票

要模拟运行进程,您可以设置ProcessStartInfo属性,并使用其他凭据运行应用程序而不会出现任何问题。您不需要使用ProcessStartInfo

只需确保其他用户有权访问应用程序的文件夹(在以下示例中为WindowsIdentity.RunImpersonated)。

App1.exe

这是一个简单的控制台应用程序,仅显示用户名:

C:\App1\

App2.exe

这是另一个运行using System; using System.Security.Principal; namespace App1 { class Program { static void Main(string[] args) { Console.WriteLine(WindowsIdentity.GetCurrent().Name); Console.ReadLine(); } } } 并显示用户名的简单控制台应用程序:

App1.exe

0
投票

前一段时间,我使用了以下代码:

using System;
using System.Diagnostics;
using System.Net;
using System.Security.Principal;
namespace App2
{
    class Program
    {
        static void Main(string[] args)
        {
            Console.WriteLine(WindowsIdentity.GetCurrent().Name);
            Console.WriteLine("Running App1");
            var info = new ProcessStartInfo();
            info.FileName = @"C:\App1\App1.exe";
            info.Domain = @"DOMAIN";
            info.UserName = @"USER";
            info.WindowStyle = ProcessWindowStyle.Normal;
            info.Password = new NetworkCredential("", "PASSWORD").SecurePassword;
            var process = Process.Start(info);
            process.WaitForExit();
            Console.WriteLine("App1 finished.");
            Console.WriteLine(WindowsIdentity.GetCurrent().Name);
            Console.ReadLine();
        }
    }
}

0
投票

这对我很有用。检查正在运行该进程的用户。有时用户不是管理员或无法模拟。

Processinfo创建新进程。尝试process.start,或者您可以将exe转换为util dll并在utli.testuser代码之类的代码中运行。使用主程序而非exe的dll调用方法。

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Linq;
using System.Runtime.ConstrainedExecution;
using System.Runtime.InteropServices;
using System.Security;
using System.Security.Permissions;
using System.Security.Principal;
using System.Text;
using System.Windows;
using Microsoft.Win32.SafeHandles;

namespace ZZZ
{

    partial class User : IDisposable
    {

        private string m_domain;
        private string m_user;
        private string m_pass;
        private WindowsIdentity user;
        private SafeTokenHandle safeTokenHandle;
        private WindowsImpersonationContext impContext;

        [DllImport("advapi32.dll", SetLastError = true, CharSet = CharSet.Unicode)]
        private static extern bool LogonUser(
            string lpszUsername,
            string lpszDomain,
            string lpszPassword,
            int dwLogonType,
            int dwLogonProvider,
            out SafeTokenHandle phToken);

        [DllImport("kernel32.dll", CharSet = CharSet.Auto)]
        private extern static bool CloseHandle(IntPtr handle);

        [DllImport("advapi32.dll", SetLastError = true)]
        private static extern bool RevertToSelf();

        //For the current user
        public User()
        {
            user = WindowsIdentity.GetCurrent();
        }

        // For custom user
        public User(string domain, string user, string password, bool doImepsonate = false)
        {
            m_domain = domain;
            m_user = user;
            m_pass = password;
            if (doImepsonate) this.Impersonate();
        }


        // If it's intended to incorporate this code into a DLL, then demand FullTrust.
        [PermissionSet(SecurityAction.Demand, Name = "FullTrust")]
        public void Impersonate()
        {
            if (impContext != null) throw new ImpersonationException();

            try
            {
                // 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.
                const int LOGON32_PROVIDER_DEFAULT = 0;
                //This parameter causes LogonUser to create a primary token. 
                const int LOGON32_LOGON_INTERACTIVE = 2;

                // Call LogonUser to obtain a handle to an access token. 
                bool returnValue = LogonUser(
                    m_user,
                    m_domain,
                    m_pass,
                    LOGON32_LOGON_INTERACTIVE,
                    LOGON32_PROVIDER_DEFAULT,
                    out safeTokenHandle);

                if (returnValue == false)
                {
                    int ret = Marshal.GetLastWin32Error();
                    throw new Win32Exception(ret);
                }

                using (safeTokenHandle)
                {
                    // Use the token handle returned by LogonUser. 
                    user = new WindowsIdentity(safeTokenHandle.DangerousGetHandle());
                    impContext = user.Impersonate();
                }
            }
            catch (Exception ex)
            {
                MessageBox.Show("Exception occurred:\n" + ex.Message);
            }
        }

        [PermissionSet(SecurityAction.Demand, Name = "FullTrust")]
        private void Quit()
        {
            if (impContext == null) return;
            impContext.Undo();
            safeTokenHandle.Dispose();
        }
        #endregion

        internal IEnumerable<string> Groups
        {
            get
            {
                return user.Groups.Select(p =>
                {
                    IdentityReference ir = null;
                    try { ir = p.Translate(typeof(NTAccount)); }
                    catch { }
                    return ir == null ? null : ir.Value;
                });
            }
        }

    }

    // Win32 API part
    internal sealed class SafeTokenHandle : SafeHandleZeroOrMinusOneIsInvalid
    {
        private SafeTokenHandle() : base(true) { }

        [DllImport("kernel32.dll")]
        [ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)]
        [SuppressUnmanagedCodeSecurity]
        [return: MarshalAs(UnmanagedType.Bool)]
        private static extern bool CloseHandle(IntPtr handle);

        protected override bool ReleaseHandle()
        {
            return CloseHandle(handle);
        }
    }

    internal sealed class ImpersonationException : Exception
    {
        public ImpersonationException() : base("The user is already impersonated.") { }
    }

}
© www.soinside.com 2019 - 2024. All rights reserved.