作为远程进程读取/写入网络位置时访问被拒绝

Access denied when reading / writing to network location as a remote process

我目前正在尝试使用 C# 中的 WMI 在远程计算机上启动进程。该进程读取和写入存储在单独服务器上的文件。

当我手动登录远程机器时,我可以运行这个过程并且一切正常。

但是,当我尝试使用 WMI 从我的本地计算机远程启动进程时,出现以下错误:

System.UnauthorizedAccessException: Access to the path '\server\path\input.txt' is denied.

我已经尝试了多种连接选项,但我不确定如何重新创建我在手动登录时似乎拥有的权限...我需要做什么?

本地机器码

static void LaunchRemoteProcess(string remoteMachine, string command)
{
    ConnectionOptions connectionOptions = new ConnectionOptions
    {
        Impersonation = ImpersonationLevel.Impersonate,
        EnablePrivileges = true
    };

    var managementScope = new ManagementScope(string.Format(@"\{0}\root\cimv2", remoteMachine), connectionOptions);
    managementScope.Connect();
    var managementPath = new ManagementPath("Win32_Process");
    var objectGetOptions = new ObjectGetOptions();
    var managementClass = new ManagementClass(managementScope, managementPath, objectGetOptions);

    // Launch the command asynchronously
    var inParams = managementClass.GetMethodParameters("Create");
    inParams["CommandLine"] = command;
    var outParams = managementClass.InvokeMethod("Create", inParams, null);
}

远程机器码

string networkPath = @"\server\path";
string inputFile = "input.txt";
string inputText = File.ReadAllText(Path.Combine(networkPath, inputFile));

string outputFile = "output.txt";
File.WriteAllText(Path.Combine(networkPath, outputFile), inputText);

编辑 1

如果我手动登录到远程计算机,我已经尝试使用该进程所针对的用户的凭据,但该进程仍然失败并出现相同的错误:

    ConnectionOptions connectionOptions = new ConnectionOptions
    {
        Username = "username",
        Password = "password",
        Authority = "ntlmdomain:COMPANYNAME.CO.UK,
        EnablePrivileges = true
    };

关于 AuthorityAuthenticationImpersonation 属性,我是否遗漏了什么?

如原因所述,您在 PC 上使用的用户 ID 似乎无法访问另一台计算机的位置(虽然它是服务器,但它是其他计算机)。

您可以使用您的用户 ID 获得访问权限,或者使用模拟来使用已经有权访问该位置的用户 ID。

在此处查找更多详细信息:https://msdn.microsoft.com/en-us/library/w070t6ka%28v=vs.110%29.aspx

已编辑:也添加用户名密码。这可能会有所帮助。

模仿与授权

您的 WMI 代码使用模拟,因此服务器端在调用客户端代码的用户的安全上下文中运行。但这仅在服务器本身有效,不适用于访问,例如远程 CIFS 共享(如您的情况)。

你必须使用委派。

首先,改变

Impersonation = ImpersonationLevel.Impersonate,

Impersonation = ImpersonationLevel.Delegate,

如果您遇到异常,则委托在您的环境中还不起作用。

检查:

  • 调用用户帐户:"Account is sensitive and cannot be delegated" 不得在用户属性(Active Directory 用户和计算机)中选中

  • 服务器机器账号:"Trust this computer for delegation to any service..."必须勾选

  • 服务器上的本地安全策略:"Enable computer and user accounts to be trusted for delegation" 必须包括调用用户。

https://msdn.microsoft.com/en-us/library/aa389288%28VS.85%29.aspx

有关此主题的更多信息。


已添加:(见下面的评论):

如果 Delegate 在您的环境中不是一个选项(例如,组策略不允许这样做,并且您无权更改它们),您可以检查一些替代方法。

你可能听说过 psexec。

或者,我几年前所做的,并且在企业环境中的生产中在几台服务器上运行了很多年,非常成功:

我创建了一个启动程序的计划任务,并为此任务设置了技术用户+密码。任务配置为 "run once in year 2200 :-)"。

然后我在队列中编写命令(我使用了一个简单的命令文件)并从远程机器启动任务。

这样做,不需要委派,因为计划任务本身以技术用户帐户登录(需要 "logon as batch" 权限)。