c# - MVC : start process as different user - not working

标签 c# asp.net-mvc process impersonation

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

只用 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();

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

像这样使用模拟:
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);

这正确地为我提供了该过程应使用的所需用户名。该用户具有本地管理员权限,因此那里不应该有问题。

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

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

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

Edit:



我的描述的一部分似乎不正确:使用模拟和 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 覆盖了进程的模拟?

不过仍然不行,因为现在我收到“拒绝访问”错误。尽管是本地管理员。这很奇怪。

Edit 2: This is how my latest attempt went:


  • 切换回调用帮助程序 .exe,传递稍后用于 Program Files
  • 中实际目标 exe 的相同参数
  • 使用 level="requireAdministrator" 将 list 添加到该帮助程序 exe
  • 根据 https://msdn.microsoft.com/en-us/library/w070t6ka(v=vs.110).aspx 在我的助手 exe 中添加了模拟与 [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);
        }
    }
    

    结果输出到error.log:

    Helper running! [passed argument] Error running process: System.ComponentModel.Win32Exception (0x80004005): Access denied at System.Diagnostics.Process.StartWithCreateProcess(ProcessStartInfo startInfo) at System.Diagnostics.Process.Start() at System.Diagnostics.Process.Start(ProcessStartInfo startInfo) at RunClient.ImpersonationDemo.RunClient(String settingsPath) Running as: [correct domain user in Admin group]



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

    这个逻辑让我难以理解。

    Edit 3



    更新:我也向目标 .exe 添加了一个 list ,
    <requestedExecutionLevel level="requireAdministrator" uiAccess="false" />
    这意味着我现在:
  • 从 Controller 调用辅助 exe:works
  • 帮助程序 .exe 有一个 list ,可以使用提升的权限运行(管理员)
  • 帮助程序 .exe 使用模拟来假设本地管理员的身份来启动进程
  • 所述进程使用 ProcessStartInfo 启动,其中用户名、域和密码另外设置为相同的本地管理员用户
  • 然后帮助 exe 尝试使用 Process.Start(Startinfo) 运行目标 exe。使用本地管理员用户集,同时仍然冒充该用户的 Windows 身份

  • 在正确返回 WindowsIdentity.GetCurrent().Name 时,错误日志仍然显示“访问被拒绝”。作为本地管理员。

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

    真的吗?

    Edit 4



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

    最佳答案

    根据this article您的 mvc Controller 线程应该具有运行进程的完全信任权限:

    This class contains a link demand at the class level that applies to all members. A SecurityException is thrown when the immediate caller does not have full-trust permission. For details about security demands, see Link Demands.



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

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

    关于c# - MVC : start process as different user - not working,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/38327197/

    相关文章:

    c# - 如何将 C# 库添加到 Monaco 编辑器(代码完成)并限制可能的库?

    android - 将 Android 手机与 ASP.net MVC 4 应用程序连接的 Web 服务

    asp.net-mvc - CQRS 读取模型中的访问规则

    c - 如何使用信号量在 fork 进程之间切换?

    c# - 如何使用 C# 中的 KeyDown 事件使 TextBox 仅接收数字键值?

    c# - MonoTouch - 从主包中读取文件

    c# - WPF Web 浏览器问题

    asp.net-mvc - CSS Select List 那个 'drops' 到右边

    c# - 我如何判断 IOException 是否是由另一个进程使用该文件这一事实引起的?

    c# - 使用 BinaryReader 在 .NET 中重定向标准输出 - 检测 EOS/强制超时