为什么 FindByIdentity 与域上下文忽略参数中的本地机器名称?

Why is FindByIdentity with Domain Context ignoring local machine name in argument?

所以我有这个字符串:

testvm\Administrator

我的机器主机名是 'testvm',我使用具有该名称的域上下文调用 FindByIdentity。问题是 FindByIdentity 正在 returning domain 管理员帐户(我知道因为它有一个非空的域帐户的 UPN 而本地帐户不能有 UPN ).那么为什么它会忽略字符串的主机名部分呢? FindByIdentity return 不应该为 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 return 在域上下文中为空,如果我在本地上下文中调用它则为非空。为什么?

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

  1. 具有域上下文的 PrincipalContext 构造函数采用本地域。如果您不想假定一个域,则必须在下一个参数中明确地告诉它是哪个域。对于机器上下文,您必须让它假定为本地机器或在下一个参数中指定您想要的机器。

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

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

  1. 像上面的字符串一样用原始账户构造一个NTAccount对象。不幸的是,能够构造对象仅意味着输入字符串不为空。所以为了到达任何地方,我们必须将对象转换成其他东西。像一个 SID。
  2. 致电: NTAccount.Translate(typeof(SecurityIdentifier)).Value 并将 SID 存储在 returns.

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

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

然后我有一个用户或组: a) 有效的'DOMAIN_OR_MACHINE\USER_OR_GROUP'格式的账号字符串。 b) 我知道它是域(和指定域的一部分)还是属于机器 c) 看Principal对象就知道是用户还是组。

这样就解决了我的问题。很乱,我认为微软将这个过程变成了 PITA,但它确实有效。

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