我有一个在特定用户帐户下运行的Windows服务(用.NET 1.1编写),以及在多个服务器上运行的服务实例。
我想将用户凭据(用户名,密码,域)从WinForms应用程序传递给服务,并让服务器的本地文件系统中的服务读/写文件模拟传入的凭据。
传递用户名,域名和密码并让Windows服务执行模拟会更好吗?我没有看到如何序列化WindowsIdentity并传递一个作为参数,让服务然后围绕I / O执行Impersonate()和Undo()。
作为容器对象,System.Net.NetworkCredential未标记为可序列化,因此传递三个单独的参数似乎是合乎逻辑的。我基本上使用KB306158中的模拟例程。
答案 0 :(得分:4)
简短的回答是:根本不通过凭据。这种做法是不安全的。
相反,您应该考虑利用操作系统提供的安全机制来实现您想要做的事情。它被称为SSPI(安全支持提供程序接口)。使用此过程会交换由OS级安全提供程序生成的一系列令牌,以设置安全上下文,而无需在用户模式代码中传递凭据。
如果您能够将服务升级为使用.NET 3.5,则可以使用WCF来执行IPC,并且在适当配置后,它将处理SSPI握手的详细信息,并直接启用模拟。
如果您遇到.NET 1.1,请查看提供的文章和示例代码here和here,其中介绍了如何从托管代码调用SSPI并使用它来保护.NET远程通道。
答案 1 :(得分:1)
我不知道这与您的需求有直接关系,但这是我在应用程序中使用的模拟代码的片段,该应用程序访问给定有效凭据的远程计算机的注册表和文件系统。 LogonUser方法将用户名密码和servername作为args,您可以通过winform app传递它。
编辑您必须在winform应用程序和在不同计算机上运行的服务之间设置一种进程间通信形式。我很抱歉,我认为这是一个关于如何模仿不如何向您的流程发送信息的问题。就IPC的方法而言,有很多选择。看看this site,它将提供比我更多的信息。你最好的选择是使用命名管道。
[DllImport("advapi32.dll",EntryPoint = "LogonUser", SetLastError = true)]
public static extern bool LogonUser(string lpszUsername, string lpszDomain, string lpszPassword,
int dwLogonType, int dwLogonProvider, ref IntPtr phToken);
IntPtr admin_token = IntPtr.Zero;
WindowsIdentity wid = WindowsIdentity.GetCurrent();
WindowsIdentity wid_admin;
WindowsImpersonationContext wic;
if (LogonUser(user, servername, pass, 9, 0, ref admin_token))
{
wid_admin = new WindowsIdentity(admin_token);
wic = wid_admin.Impersonate();
//do stuff with new creds here
}
答案 2 :(得分:1)
我认为你不能将Network Credential对象直接传递给另一个进程,它基于一个底层的windows api,我猜测会让各个进程绕过他们的auth令牌而涉及各种糟糕的juju。
如果可能,我会采用您提到的方法,并将登录凭据(用户/通行证)传递给服务,并让它用于模拟。