作为远程进程读取/写入网络位置时访问被拒绝
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
};
关于 Authority
、Authentication
或 Impersonation
属性,我是否遗漏了什么?
如原因所述,您在 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" 权限)。
我目前正在尝试使用 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
};
关于 Authority
、Authentication
或 Impersonation
属性,我是否遗漏了什么?
如原因所述,您在 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" 权限)。