从Active Directory组获取所有用户

时间:2018-10-12 20:09:30

标签: c# active-directory

我正在使用以下代码从特定域中的特定Active Directory组获取所有用户。这段代码可以正常工作。

using (var context = new PrincipalContext(ContextType.Domain, "dept.mycomp.net"))
{
    using (var group = GroupPrincipal.FindByIdentity(context, "IT Team"))
    {
        if (group != null)
        {
            var users = group.GetMembers(true);

            foreach (UserPrincipal user in users)
            {
                Console.WriteLine("Name: " + user.DisplayName);
                Console.WriteLine("Network Id: " + user.SamAccountName);
            }
        }
    }
}

我看到Active Directory查找窗口中有Entire Directory选项。所以我搜索了一下,发现以下代码;这段代码将使我从Entire Directory根级别吸引所有用户。在我的情况下,此代码也可以正常工作:

var currentForest = Forest.GetCurrentForest();
var gc = currentForest.FindGlobalCatalog();

using (var userSearcher = gc.GetDirectorySearcher())
{
    userSearcher.Filter = "(&((&(objectCategory=Person)(objectClass=User)))(samaccountname=" + username + "))";
    SearchResult result = userSearcher.FindOne();
}

问题:如何修改以后的代码以在根级别获取特定组的所有用户?我只会传递GroupName而不是Domain & Group Name

1 个答案:

答案 0 :(得分:0)

Entire Directory选项会搜索全局目录,而不仅仅是查找域,因为看起来好像已经找到了。搜索的唯一区别是它连接到哪个端口。端口389是LDAP端口,它仅搜索您要连接的服务器的域。端口3268是全局目录。一种简短的形式是使用GC://而不是LDAP://

如果您仅在了解域的单一环境中工作,则可以对其进行硬编码。它将保存GetCurrentForest()FindGlobalCatalog()的网络请求。

这是我的意思:

var searcher = new DirectorySearcher(new DirectoryEntry("GC://dept.mycomp.net"));

关于搜索特定组的其他问题:请记住,全局目录搜索您的AD林,该林可以是多个域。任何对象的名称仅在域(而不是目录林)中强制唯一。因此,如果您在GC中搜索组的名称,则可能会出现重复。 (您所有域中可能都有一个“ IT团队”组)

但是无论如何,如果我们假设您在整个林中只有该名称的一组,这就是您搜索它并获得成员的方式:

var groupname = "IT Team";
var members = new List<string>();
using (var searcher = new DirectorySearcher(new DirectoryEntry("GC://dept.mycomp.net"))) {
    searcher.Filter = "(&(objectCategory=group)(objectClass=group)(cn=" + groupname + "))";
    searher.PropertiesToLoad.Add("member"); //only get the member attribute

    using (SearchResult result = searcher.FindOne()) {
        foreach (var member in result.Properties["member"]) {
            members.Add(member);
        }
    }
}

完成后,members将是每个成员的distinguishedName的列表。如果您想要一个不同的属性(例如displayName),则需要为每个成员创建一个DirectoryEntry并获取该属性。

有一些警告可能并不相关:

  1. 该组中可能有多个组。这不会寻找这些组的成员。
  2. 如果您的域与林外的另一个域信任,则来自该外部域的成员的显示方式会有所不同。我在自己的网站上发表了一篇名为What makes a member a member?
  3. 的文章
  4. 这可能会或可能不会将您看到的成员数限制为最多1000个(如果该组有1000个以上的成员)。我不记得这种方法是否会发生这种情况。我知道从DirectoryEntry读取'member'属性时会这样做。如果您的团队规模不大,那么这不是问题。