c# - 客户端/服务器应用程序,如何以域用户的身份在远程系统上创建进程,而不将该用户的用户名/密码传输到远程系统?
问题描述
我有两个系统都运行我的 C# 客户端/服务器软件代码。我想从计算机 1 创建一个进程作为计算机 2 上的给定 Active Directory 域用户,而不必让我的客户端/服务器软件将 AD 用户的纯文本用户名和密码从计算机 1 发送到计算机 2。
我得到的最接近的似乎是我可以使用计算机 1 上的函数 KerberosRequestorSecurityToken 生成一个 kerberos 票证,然后通过我的客户端/服务器代码将该字节 [] 结果发送到计算机 2,然后它应该能够调用 KerberosReceiverSecurityToken 反对已通过的 byte[] kerberos 票证。如果一切正常,那么 KerberosReceiverSecurityToken 将具有 WindowsIdentity 属性,然后我可以使用该属性在计算机 2 上创建一个进程,用户帐户最初通过 KerberosRequestorSecurityToken 流在计算机 1 上指定。
我需要使用要模拟的现有域用户帐户与注册服务帐户 SPN。这是我最初发布问题时没有提及的问题的症结所在。
我似乎无法让它工作,但更多所以我什至不知道这是否真的可能 - 例如,这些 API 是否应该允许我做我想做的事?
用于生成 kerberos 票证的计算机 1 代码。byte[] 结果通过我的客户端/服务器应用程序发送到计算机 2。
public static byte[] GetRequestToken(string userName, string password, string domain)
{
using (var domainContext = new PrincipalContext(ContextType.Domain, domain))
{
using (var foundUser = UserPrincipal.FindByIdentity(domainContext, IdentityType.SamAccountName, userName))
{
Console.WriteLine("User Principal name" + UserPrincipal.FindByIdentity(domainContext, IdentityType.SamAccountName, userName).UserPrincipalName);
string spn = UserPrincipal.FindByIdentity(domainContext, IdentityType.SamAccountName, userName).UserPrincipalName;
KerberosSecurityTokenProvider k1 = new KerberosSecurityTokenProvider(spn, TokenImpersonationLevel.Impersonation, new NetworkCredential(userName, password, domain));
KerberosRequestorSecurityToken T1 = k1.GetToken(TimeSpan.FromMinutes(1)) as KerberosRequestorSecurityToken;
var req = T1.GetRequest();
return req;
}
}
}
计算机 2 获取生成的 byte[] kerberos 票证并尝试接收它以访问 WindowsIdentity,但它会引发异常登录无效。
KerberosReceiverSecurityToken receiverToken = new KerberosReceiverSecurityToken(requestToken);
byte[] receiverTokenTicket = receiverToken.GetRequest();
//Identity for impersonation
var impersonatedIdentity = receiverToken.WindowsIdentity;
解决方案
第一个代码块的来源在功能上是错误的。SPN 必须是接收票证的目标,而不是请求票证的用户。所以你需要做以下事情......
- 在 AD 中注册服务主体帐户(用户/计算机)。
- 将服务主体名称添加到该帐户,
foo/host.domain.com
其中 foo 是您的服务名称,例如http
orhost
、 ormyapp
。 - 客户需要申请一张票到
foo/host.domain.com
KerberosReceiverSecurityToken
应该解析那张票
现在你有一个不同模拟级别的身份。该模拟级别决定了您是否可以以该用户身份启动进程。碰巧......你不能,因为这不是 Windows 安全的工作方式。因为您正在模拟用户,所以您有一个模拟 NT 令牌,而您需要一个主 NT 令牌来启动进程。
因此,您需要使用DuplicateTokenEx将其转换为主令牌,并且您实际上需要 SYSTEM 才能做到这一点。
获得主令牌后,您可以调用CreateProcessAsUser。
此时,您可能已经以用户身份启动了该过程,但它没有任何凭据来访问其他网络属性,例如网络共享或 Web 服务。为此,您可以在服务主体上为任何下游服务启用约束委派。
另一种可能更安全、更容易的选择是作为低权限用户启动工作进程并告诉该进程进行模拟。有关更多信息,请参阅此答案。
推荐阅读
- paperjs - 如何更改 Paper.js 中的默认单位?
- sql - 在变量 plsql 中获取逗号分隔的 ID
- eclipse - 两个不同版本的 perl 产生不同的结果是否正常?
- javascript - 使用 REST API 中的 ID 更改特定卡片的 onClick 按钮文本
- python - 生成一个 numpy 随机数请参阅从均值 1 和标准差 2 的正态分布中抽取的 100 个随机数数组
- dart - Flutter - 无法使用 FAB 而不是 TabBar 图标更改选项卡
- sql-server - 如何在 EntityFrameworkCore 中使用差异函数?
- python - Python - 是否可以使用空白列创建连接字符串
- php - 如何从选定的月份获取上个月
- ionic-framework - ionic 3 从标签页到普通页