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

Loc*_*eer 2 c# asp.net-mvc impersonation process

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

只运行exe Process.Start(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();
Run Code Online (Sandbox Code Playgroud)

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

使用这样的模拟:

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

...用RunClient()简单的方法使用Process.Start(exe)将绝对没有!运行该方法但该过程未启动.我知道该方法是运行的,因为我添加了这一行:

_logger.Debug("Impersonated: {0}", Environment.UserName);
Run Code Online (Sandbox Code Playgroud)

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

我甚至试图从开始我的控制器不同的可执行文件,并有一个使用模拟(两种款式)启动目标可执行文件-相同的结果.

所以现在我走到了尽头.任何人都可以告诉我我做错了什么以及我必须做些什么来使它工作?

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);
Run Code Online (Sandbox Code Playgroud)

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

var proc = Process.Start(exe, argument);
Run Code Online (Sandbox Code Playgroud)

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

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

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

  • 切换回调用帮助器.exe,传递稍后用于Program Files中的实际目标exe的相同参数
  • 为该助手exe添加了一个清单 level="requireAdministrator"
  • 根据添加模拟来帮助我的exe https://msdn.microsoft.com/en-us/library/w070t6ka(v=vs.110).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);
    }
}
Run Code Online (Sandbox Code Playgroud)

结果输出到error.log:

帮手跑![传递参数]运行错误的进程:System.ComponentModel.Win32Exception(0x80004005):在System.Diagnostics.Process.Start的System.Diagnostics.Process.Start()处的System.Diagnostics.Process.StartWithCreateProcess(ProcessStartInfo startInfo)中拒绝访问( ProcessClartInfo startInfo)在RunClient.ImpersonationDemo.RunClient(String settingsPath)运行方式:[管理员组中的正确域用户]

所以,我可以启动辅助exe文件,但认为由于接取否认,尽管在本地管理员帐户运行时无法启动程序文件的真实EXE和所有的文件访问本地,而不是网络驱动器上.

这种逻辑使我望而却步.

编辑3

更新:我已经向目标.exe添加了一个清单,

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

这意味着我现在:

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

而且还是错误日志嘴"拒绝访问",而正确地恢复WindowsIdentity.GetCurrent().Name为本地管理员的.

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

真?

编辑4

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

Ale*_*ets 5

根据这篇文章,你的mvc控制器线程应具有完全信任的权限来运行该进程:

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

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

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