MVC:以不同用户身份启动进程 - 不工作

本文关键字:进程 启动 工作 身份 用户 MVC | 更新日期: 2023-09-27 17:56:37

我需要从MVC控制器在服务器上运行可执行文件。问题:可执行文件位于程序文件文件夹中,还将从注册表中读取值。我已向我的应用程序池授予了相应文件夹的执行权限。所以这是我的问题:

仅使用 Process.Start(exe) 运行 exe 将启动可执行文件,然后该可执行文件又退出并显示错误,因为它无法读取注册表值(无访问权限)。

将本地管理员用户分配给ProcessStartInfo失败:

var exe = @"C:'Program Files (x86)'[path to exe]";
var secString = new SecureString();
secString.AppendChar('character');
//...
secString.MakeReadOnly();
var procInfo = new ProcessStartInfo(exe, settingsPath)
{
    UseShellExecute = false,
    UserName = "[username]",
    Domain = "[domain]",
    Password = secString,
    RedirectStandardError = true,
    RedirectStandardOutput = true,
    RedirectStandardInput = true,
    Verb = "runas"
};
var proc = Process.Start(procInfo);
proc.WaitForExit();

这将导致主机和可执行文件崩溃。

像这样使用模拟:

var impers = new ImpersonationService();
impers.PerformImpersonatedTask("[user]", "[domain]", "[password]",
ImpersonationService.LOGON32_LOGON_INTERACTIVE, ImpersonationService.LOGON32_PROVIDER_DEFAULT, new Action(RunClient));

。使用这种方法RunClient()简单地使用Process.Start(exe)绝对不会做任何事情!该方法已运行,但进程未启动。我知道该方法正在运行,因为我在其中添加了以下行:

_logger.Debug("Impersonated: {0}", Environment.UserName);

这正确地给了我进程应使用的所需用户名。该用户具有本地管理员权限,因此应该没有问题。

我什至尝试从我的控制器启动不同的可执行文件,并让可执行文件使用模拟(两种变体)来启动目标可执行文件 - 相同的结果。

所以现在我处于死胡同。谁能告诉我我做错了什么以及我必须做些什么才能让它发挥作用?

PS:以本地管理员用户身份登录时直接在服务器上运行目标可执行文件工作得很好,因此 exe 本身没有问题。

编辑:

似乎我的描述的一部分不正确:对于模拟和 RunClient 方法,我实际上没有使用Process.Start(exe)而是使用这个:

var procInfo = new ProcessStartInfo(exe, settingsPath)
{
    UseShellExecute = false,
};
_logger.Debug("Impersonated: {0}", Environment.UserName);
var proc = Process.Start(procInfo);

出于绝望,我现在已经规避了procInfo(实际上不需要它)并真正打电话

var proc = Process.Start(exe, argument);

现在.exe开始了!似乎使用ProcessStartInfo覆盖了进程的模拟?

仍然不行,因为现在我收到"访问被拒绝"错误。尽管是本地管理员。这太奇怪了。

编辑 2: 这就是我最近的尝试:

  • 切换回调用帮助程序.exe,传递稍后在程序文件中用于实际目标 exe 的相同参数
  • 向该帮助程序 EXE 添加了清单,其中包含level="requireAdministrator"
  • 根据 https://msdn.microsoft.com/en-us/library/w070t6ka(v=vs.110)将模拟添加到我的帮助程序 exe 中.aspx并在方法启动目标进程之前添加了[PermissionSetAttribute(SecurityAction.Demand, Name = "FullTrust")]
  • 通过向 ProcessStartInfo 提供所有爵士乐来开始该过程

生成的代码:

try
{
    var secString = new SecureString();
    //...
    secString.MakeReadOnly();
    var procInfo = new ProcessStartInfo()
    {
        FileName = Path.GetFileName(exe),
        UserName = "[UserName]",
        Domain = "[domain]",
        Password = secString,
        UseShellExecute = false,
        RedirectStandardError = true,
        RedirectStandardOutput = true,
        RedirectStandardInput = true,
        Arguments = settingsPath,
        WorkingDirectory = @"C:'Program Files (x86)'[rest]"
    };
    var proc = Process.Start(procInfo);
    proc.WaitForExit();
    if (proc.ExitCode != 0)
    {
        using (var sw = new StreamWriter(Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "error.log"), true))
        {
            sw.WriteLine("Error running process:'r'n{0}", proc.ExitCode.ToString());
        }
    }
}
catch (Exception ex)
{
    using (var sw = new StreamWriter(Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "error.log"), true))
    {
        sw.WriteLine("Error running process:'r'n{0}'r'nRunning as: {1}", ex.ToString(), WindowsIdentity.GetCurrent().Name);
    }
}

导致输出错误.log:

帮手跑! [传递的参数] 运行进程时出错:系统.组件模型.Win32异常 (0x80004005): 访问被拒绝 System.Diagnostics.Process.StartWithCreateProcess(ProcessStartInfo startInfo) at System.Diagnostics.Process.Start() at System.Diagnostics.Process.Start(ProcessStartInfo startInfo) at RunClient.ImpersonationDemo.RunClient(String settingsPath) 运行身份:[管理员组中正确的域用户]

所以我可以启动帮助程序 exe,

但由于 Acess 被拒绝,尽管在本地管理员帐户下运行并且所有文件都在本地访问,而不是在网络驱动器上,但无法在程序文件中启动真正的 exe。

这其中的逻辑让我无法理解。

编辑 3

更新:我也在目标.exe中添加了一个清单,

<requestedExecutionLevel level="requireAdministrator" uiAccess="false" />

这意味着我现在:

  • 从控制器调用帮助程序 exe:有效
  • 帮助程序.exe具有使用提升的权限运行的清单(管理员)
  • 帮助程序.exe使用模拟来假定本地管理员的身份来启动进程
  • 所述进程使用ProcessStartInfo启动,其中用户名,域和密码另外设置为相同的本地管理员用户
  • 然后,帮助程序 exe 尝试使用具有本地管理员用户集的 Process.Start(Startinfo) 运行目标 exe,同时仍模拟该用户的 windows 标识

并且错误日志仍然喷出"访问被拒绝",同时正确返回本地管理员WindowsIdentity.GetCurrent().Name

现在,最伟大的事情发生了:我在该服务器上创建了一个新的本地用户,将他添加到本地管理员组,并使用该用户进行模拟,以防域用户出现问题。你猜怎么着?现在我收到一个错误Access denied to ...'error.log - 写入 effing 错误日志。

真?

编辑 4

我想我会尝试 TopShelf 将这个 shebang 转换为服务。希望在周末完成这项工作。

MVC:以不同用户身份启动进程 - 不工作

根据本文,您的 mvc 控制器线程应具有完全信任权限才能运行该进程:

此类包含类级别的链接需求,该要求适用于 所有成员。当直接调用方时引发安全异常 没有完全信任权限。有关安全性的详细信息 需求,请参阅链接需求。

看来你的问题不是用户,而是完全信任。我不知道您使用哪个版本的 MVC,但您可以阅读文章信任级别和代码访问,以找出配置应用程序的最佳方法。似乎您只能向特定文件授予完全信任权限.exe或向应用程序池用户授予完全信任权限(不要忘记文件夹权限)。

但最好的方法是编写一些Windows服务并运行它,而不是直接运行一些.exe文件。

您可以在应用程序web.config尝试信任级别

<system.web>
  <securityPolicy>
    <trustLevel name="Full" policyFile="internal"/>
  </securityPolicy>
</system.web>