【问题标题】:Access Denied starting process from ASP.NET website从 ASP.NET 网站访问被拒绝启动过程
【发布时间】:2019-08-27 15:50:04
【问题描述】:

我有一个 ASP.NET MVC4 网站,我试图在服务器上执行一个进程。代码如下:

ProcessStartInfo startInfo = new ProcessStartInfo()
{
    FileName = ExeLocation,
    Arguments = string.Format("\"{0}\"{1}", ScriptLocation, Arguments),
    UseShellExecute = false,
    RedirectStandardOutput = true,
    RedirectStandardError = true,
    WorkingDirectory = AppDir,
    CreateNoWindow = true,
    UserName = ExeUsername,
    Password = ExePassword,
    Domain = ExeDomain
};

using (Process process = Process.Start(startInfo))
{
    using (StreamReader reader = process.StandardOutput)
    {
        output = reader.ReadToEnd();
    }
    using (StreamReader reader = process.StandardError)
    {
        error = reader.ReadToEnd();
    }
    process.WaitForExit();
    if (process.ExitCode != 0)
    {
        throw new Exception(string.IsNullOrEmpty(output) ? error : output);
    }
}

这在 Visual Studio 中的本地计算机上运行良好,但是当我部署到我的服务器 (W2K12) 时,我收到以下错误:

Access is denied   
at System.Diagnostics.Process.StartWithCreateProcess(ProcessStartInfo startInfo)

我在服务器上的 AdministratorsIIS_IUSRS 组中都有 ExeUsername 引用的帐户。

应用程序池作为不同的帐户运行(因此需要分配一个特定的帐户来运行进程),该帐户也是服务器上管理员和 IIS_IUSRS 的成员。

当我登录服务器并以ExeUsername 运行命令提示符时,我能够执行该进程,因此问题必须与从 IIS 执行有关。

还有什么可能阻止此访问?

【问题讨论】:

  • 您的 ApplicationPool 身份是否有权访问ExeLocation
  • 另一种方法是授予 IIS_IUSERS 内置组对您要访问的文件夹的权限。这将为 所有 默认应用程序池提供访问权限,因此请考虑您的用例
  • @kapsiR ApplicationPool 身份也在管理员和 IIS_IUSRS 中
  • @Paul 是的,但是该身份可以访问可执行文件并有权执行该过程吗? Take a look at this question/answer

标签: c# asp.net windows-server-2012


【解决方案1】:

也许使用它会对你有所帮助。

ProcessStartInfo startInfo = new ProcessStartInfo()
{
   //...
   UseShellExecute = true,                
   Verb = "runas"
};

如果您遇到错误,您也可以查看this

【讨论】:

    【解决方案2】:

    我会尝试不同的方法。首先模拟一个自定义用户(有权运行命令的用户),然后在模拟用户的上下文中启动一个进程:

    SafeAccessTokenHandle safeAccessTokenHandle;  
    bool returnValue = LogonUser(ExeUsername, ExeDomain, ExePassword,  
            LOGON32_LOGON_INTERACTIVE, LOGON32_PROVIDER_DEFAULT,  
            out safeAccessTokenHandle);
    
    if (false == returnValue)  
    {  
        int ret = Marshal.GetLastWin32Error();  
        throw new System.ComponentModel.Win32Exception(ret);  
    }  
    
    WindowsIdentity.RunImpersonated(safeAccessTokenHandle, () =>  
    {  
         var startInfo = new ProcessStartInfo()
         {
             FileName = ExeLocation,
             Arguments = string.Format("\"{0}\"{1}", ScriptLocation, Arguments),
             UseShellExecute = false,
             RedirectStandardOutput = true,
             RedirectStandardError = true,
             WorkingDirectory = AppDir,
             CreateNoWindow = true,
             UserName = ExeUsername,
             Password = ExePassword,
             Domain = ExeDomain
         };
    
         using (Process process = Process.Start(startInfo))
         {
             using (StreamReader reader = process.StandardOutput)
             {
                 output = reader.ReadToEnd();
             }
    
             using (StreamReader reader = process.StandardError)
             {
                 error = reader.ReadToEnd();
             }
    
             process.WaitForExit();
             if (process.ExitCode != 0)
             {
                 throw new Exception(string.IsNullOrEmpty(output) ? error : output);
             }
         } 
    );  
    

    LogonUser 方法如下所示:

    [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);
    

    有关在 .NET 中模拟的更多信息在这里:https://docs.microsoft.com/en-gb/dotnet/api/system.security.principal.windowsidentity.runimpersonated?view=netframework-4.7.2

    【讨论】:

    • 我尝试了类似的方法,但仍然没有运气。该 exe 仍作为应用程序池标识运行。我的代码在 .NET 4.0 中:docs.microsoft.com/en-us/dotnet/api/…
    • 所以模拟有效,但是当您在模拟用户的上下文中调用 Process.Start 时,应用程序仍然会抛出访问被拒绝?能不能把pool的临时标识改成Local system,看看错误是否依然存在?
    • 如果我将 AppPool 作为 LocalSystem 运行,在向 Process.Start 提供用户名/密码时,我仍然会收到拒绝访问错误。如果我从 Process.Start 中删除用户名/密码,它将成功运行,但作为 AppPool 帐户。我的目标是作为指定帐户运行该进程,而我的 AppPool 作为另一个帐户运行(由于环境的另一个要求)。
    • 好的,你能再尝试一件事吗...创建一个简单的控制台应用程序,只使用你在问题中发布的代码(带有 ExeUsername 的 ProcessStartInfo)并尝试在服务器上运行它。有用吗?
    • 我在服务器上使用原始代码作为 AppPool 帐户运行了一个控制台应用程序,但没有收到错误消息。所以它肯定似乎与应用程序在 IIS 下使用 ASP.NET Impersonation 运行的方式有关。
    【解决方案3】:
    1. 右键单击应用程序池
    2. 点击高级设置
    3. 身份
    4. 自定义帐户
    5. 设置用户名和密码

    如果您有域,请小心使用 domain\username 作为用户名
    还可以访问部署文件夹。

    【讨论】:

    • 我认为这只是回答了这个问题,但在 cmets 的链接中没有提供任何已接受的答案
    • 我已经在自定义帐户下运行了应用程序池。但是该过程需要以不同的帐户运行。这就是我为该进程设置特定用户名和密码的原因。
    猜你喜欢
    • 1970-01-01
    • 2015-09-25
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-12-15
    • 2018-12-20
    • 2022-08-20
    • 1970-01-01
    相关资源
    最近更新 更多