为什么Principal.IsMemberOf()会为某些组返回false negative?

时间:2014-11-17 21:03:22

标签: c# active-directory active-directory-group

为什么Principal.IsMemberOf(GroupPrincipal)MSDN)会在以下测试中为Domain Computers组返回误报?

[TestMethod]
public void DomainComputerTest()
{
    var distinguishedName = "CN=MyMachine,DC=SomeDomain,DC=local";
    using( var pc = new PrincipalContext( ContextType.Domain, "SomeDomain.local", "UserName", "Password" ) )
    using( var computer = ComputerPrincipal.FindByIdentity( pc, IdentityType.DistinguishedName, distinguishedName ) )
    {
        Assert.IsNotNull( computer );
        // Get the groups for the computer.
        var groups = computer.GetGroups().Cast<GroupPrincipal>();
        foreach( var group in groups )
        {
            // Immediately turn around and test that the computer is a member of the groups it returned.
            Assert.IsTrue( computer.IsMemberOf( group ), "Computer is not member of group {0}", group.Name );
        }
    }
}

结果消息:Assert.IsTrue失败。计算机不是“域名计算机”的成员。组

计算机确实是&#34; Domain Computers&#34;的成员。组,其中&#39; GetGroups()&#39;方法正确返回。实际上,如果您尝试将计算机添加到组中,则会抛出PrincipalExistsException。

我可以重现与用户和&#34;域用户&#34;完全相同的行为。组。这是因为这些团体是校长团体吗?是因为这些是&#34;默认&#34;组?

编辑添加:我们正在使用.NET 4.5.1。

4 个答案:

答案 0 :(得分:7)

这似乎是一直存在的问题。

我在同一个问题上发现的每个问题都没有答案。我找不到任何说这是作为bug提交的内容,但似乎自.NET 3.5以来就存在。

我试图让你的例子返回true(当然改变了我工作领域的信息)。无论如何,它返回false。在dotPeek中反编译Principal类仅得出推测。完成并设置Visual Studio以允许步入.NET框架代码是一个破坏,因为它不会进入必要的方法。我可以进入其他.NET框架代码,但Principal上没有。不确定这是否与SecurityCriticalAttribute标记的方法有关。我很乐意确认。

我的建议是将此文件作为错误提交,并在同一时间采用不同的路径来确定计算机是否为成员。在我的测试中,group.Members确实包含了计算机。

我遇到了运行.NET 3.5,4.0,4.5,4.5.1

的相同问题

以下是一些参考资料:

解决方法 - GroupPrincipal.IsMemberOf always returns false

A 2010 MSDN Blog entry with a comment that had the same issue as you.

注意:我通常不会这样回答,但因为我在这个问题上发现的每个问题都有0个答案或解决方法,我认为对未来的读者来说实际上看到某种形式是有益的。 &#34;回答&#34;关于这个问题。

答案 1 :(得分:1)

对于其他发现这一点的开发人员,这就是我最终要做的事情。这是我部署的代码的简化版本,但总的来说,我假设问题是主要组关系。 这可能不正确,但它现在对我们有效。

您可以像这样DirectoryEntry获取ComputerPrincipal个实例。

var entry = (DirectoryEntry)computerPrincipal.GetUnderlyingObject();

我正在使用此扩展方法来检查主要群组关系。

public static bool IsPrimaryGroupFor( this GroupPrincipal group, DirectoryEntry target )
{
    // .Value will return an int like "123", which is the last part of the group's SID
    var id = target.Properties[ "primaryGroupID" ].Value.ToString();
    // strip the account domain SID from the group SID.
    var groupId = group.Sid.Value.Remove( 0, group.Sid.AccountDomainSid.Value.Length + 1 );

    // If the 
    return id.Equals( groupId, StringComparison.OrdinalIgnoreCase );
}

我们正在同步AD群组成员资格,因此我们在类似以下代码中发现了此问题;

public void AddComputerToGroups( ComputerPrincipal computer, ICollection<GroupPrincipal> groups )
{
    var directoryEntry = (DirectoryEntry)computer.GetUnderlyingObject();

    foreach( var principal in groups.Where(g=> !computer.IsMemberOf(g) )
    {
        principal.Members.Add( computer );
        principal.Save(); // Exception thrown because computer already existed in the primary group.
    }
}

答案 2 :(得分:0)

因此,我相信您可能遇到的问题与我在此处所遇到的问题相同,但对于计算机帐户而非用户帐户。

Principal.IsInRole("AD Group Name") always returns false, no exceptions thrown

验证执行代码的帐户是否具有对计算机所在域中的{strong> ComputersUsers容器的读取权限导致错误/遇到问题的问题已登记。

答案 3 :(得分:0)

如果您要测试的组成员过多,也会发生这种情况。 IsMemberOf仅显示检查前1000个左右的条目。 要解决这种情况,请检查group.Members是否包含用户/计算机。