c# - .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);
}
解决方案
如果您不指定用户名和密码,Process.Start
将使用调用进程的令牌,而不是模拟令牌。
查看源代码:Process.Start
- 如果您传递它使用的用户名和密码
CreateProcess
- 如果你不指定用户名和密码,它会调用
CreateProcessWithLogon
如果调用进程正在模拟另一个用户,则新进程将使用调用进程的令牌,而不是模拟令牌。要在由模拟令牌表示的用户的安全上下文中运行新进程,请使用 CreateProcessAsUser 或 CreateProcessWithLogonW 函数。
在不传递用户名和密码的情况下,进程始终在原始进程所有者的安全上下文中运行。如果要在另一个用户的上下文中运行该进程:
- 如果您有用户名和密码:使用
CreateProcessWithLogon
- 如果您有一个代表用户使用的主令牌
CreateProcessAsUser
推荐阅读
- javascript - onclick 将值传递给弹出模式 laravel jquery
- selenium - 移动浏览器自动化
- python - 根据对值删除熊猫数据框中的行
- angular - 错误:找不到模块'@ckeditor/ckeditor5-build-classic'角度9的声明文件
- javascript - 在 Ajax 中如何显示对用户交互的输入的验证?
- python - 布林带阴影没有颜色阴影
- java - 不仅执行 main 方法(Java)是什么意思?
- python - 使用 .map 或类似文件根据特定行和列中的值创建 Pandas 列
- google-cloud-dataflow - 在 Google Dataflow 中查看作业图大小
- sql - 如何比较 SQL Server 中的 2 个字符串,如果有任何大小写差异,则不应为真