首页 > 解决方案 > .Net Core Impersonation 不适用于 Process.Start

问题描述

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

这是我为验证其是否有效而进行的众多测试RunImpersonated()之一(这最初源于 ASP.Net Core 应用程序中试图模拟当前用户的问题)。这是我能找到的最简单的可重现示例。

[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-coreimpersonationwindows-identity

解决方案


如果您不指定用户名和密码,Process.Start将使用调用进程的令牌,而不是模拟令牌。

查看源代码Process.Start

如果调用进程正在模拟另一个用户,则新进程将使用调用进程的令牌,而不是模拟令牌。要在由模拟令牌表示的用户的安全上下文中运行新进程,请使用 CreateProcessAsUser 或 CreateProcessWithLogonW 函数。

在不传递用户名和密码的情况下,进程始终在原始进程所有者的安全上下文中运行。如果要在另一个用户的上下文中运行该进程:


推荐阅读