为什么具有域上下文的FindByIdentity在参数中忽略本地计算机名称



所以我有这个字符串:

testvmAdministrator

其中我的机器主机名是"testvm",我使用该名称的域上下文调用FindByIdentity。问题是FindByIdentity正在返回管理员帐户(我知道,因为它有该域帐户的非空UPN,而本地帐户不能有UPN)。那么,为什么它会忽略字符串的主机名部分呢?FindByIdentity不应该返回null吗?因为我专门把机器主机名放在那里了?这是我的代码:

private bool GetPrincipalFromName_IsDomain(string sName, out Principal userPrincipal)
{
bool bIsDomain = false;
userPrincipal = null;
PrincipalContext pcontextDomain = null;
try
{
pcontextDomain = new PrincipalContext(ContextType.Domain);
}
catch (Exception ex)
{
throw new Exception("Unable to Initialize Domain Context", ex);
}
try
{
userPrincipal = Principal.FindByIdentity(pcontextDomain, sName);
if(userPrincipal != null)
{
bIsDomain = true;
}
}
catch(MultipleMatchesException mmEx)
{
throw new Exception(string.Format("Found more than one Principal on Domain using Name '{0}'. Use a more precise domain name.", sName), mmEx);
}
catch (Exception ex)
{
throw new Exception(string.Format("Unable to Find Principal on Domain using Name '{0}'.", sName), ex);
}
return bIsDomain;
}

我能找到的唯一解决办法是通过:

testvm\Administrator

然后FindByIdentity在域上下文中返回null,若我用本地上下文调用它,则返回非null。为什么?

我没有完全掌握的好东西:

  1. 具有域上下文的PrincipalContext构造函数假定本地域。如果你不想假设一个域,你必须在下一个参数中明确告诉它哪个域。在机器上下文的情况下,您必须让它假设本地机器,或者在下一个参数中指定您想要的机器。

  2. FindByIdentity方法不关心斜杠之前的任何内容。FindByIdentity查找一种类型的标识(IdentityReference),并默认为"Name",即用户名或组名。它需要用户或组的名称,除非您指定不同类型的标识(如SID),在这种情况下,它会在该上下文中查找主体。因此,在我的"domain\jlaird"案例中,它忽略了斜杠之前的所有内容,并在当前域中查找"jlai尔德"(我猜是进程运行的域)。

所以我需要一些方法来获取像"DOMAIN_OR_MACHINE\USER_OR_GROUP"这样的帐户字符串,并从中获取Principal对象。解决方案。。。

  1. 构造一个NTAccount对象,使用上面字符串上方的原始帐户。不幸的是,能够构造对象只意味着输入字符串不是null。因此,为了获得任何位置,我们必须将对象转换为其他对象。就像SID
  2. 电话:NTAccount.Translate(类型为(SecurityIdentifier)).Value并存储它返回的SID

如果SID不为NULL,我可以假设帐户字符串是正常的(它存在)。那么。。。

  1. 使用斜线作为分隔符从用户名或组名中分离域名。用斜线之前的内容构造域上下文
  2. 使用来自#2的SID,使用该域上下文对象调用FindByIdentity
  3. 如果FindByIdentity在域上下文中失败,请创建本地计算机上下文并使用相同SID调用FindByIdentity

然后我有一个用户或组:a) 有效的"DOMAIN_OR_MACHINE\USER_OR_GROUP"格式的帐户字符串。b) 我知道它是域(也是指定域的一部分)还是属于机器c) 通过查看Principal对象,我知道它是用户还是组。

所以这解决了我的问题。混乱,我认为微软把这个过程变成了PITA,但它是有效的。

如果这对其他人有用,请标记为答案。

最新更新