C#,AD:得到一组的成员递归,即包括亚 [英] C#, AD: get members of a group recursively, i.e. including subgroups

查看:359
本文介绍了C#,AD:得到一组的成员递归,即包括亚的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

由于一组像这样在Active Directory:

Given a group like this in Active Directory:

MainGroup
  GroupA
    User1
    User2
  GroupB
    User3
  User4

我可以很容易地确定用户3是MainGroup或成员的任何其子组与code是这样的:

I can easily determine if User3 is member of MainGroup or any of its subgroups with code like this:

using System;
using System.DirectoryServices;

static class Program {
    static void Main() {
        DirectoryEntry user = new DirectoryEntry("LDAP://CN=User3,DC=X,DC=y");
        string filter = "(memberOf:1.2.840.113556.1.4.1941:=CN=MainGroup,DC=X,DC=y");
        DirectorySearcher searcher = new DirectorySearcher(user, filter);
        searcher.SearchScope = SearchScope.Subtree;
        var r = searcher.FindOne();
        bool isMember = (r != null);
    }
}

我想知道是否有类似的办法让一切在一组或成员任其子组,即在本例中为MainGroup得到用户1,用户2,用户3和用户4的用户。

I would like to know if there is a similar way to get all the users that are member of a group or any of its subgroups, i.e. in the example for MainGroup get User1, User2, User3 and User4.

让所有用户的显而易见的方法是递归查询每个分组,但我不知道是否有更简单的方法。

The obvious way of getting all the users is to recursively query each subgroup, but I was wondering if there's an easier way.

使用的的memberOf相同的方法:1.2.840.113556.1.4.1941:过滤器,但使用用户的域根,而不是作为一个搜索的基础是不可行,作为查询时间太长(可能是计算所有组成员递归域中所有用户和检查,如果他们是在给定组的成员)。

Using the same approach with the memberOf:1.2.840.113556.1.4.1941: filter, but using the domain root instead of the user as a search base is not feasible, as the query takes too long (probably it computes all the group memberships recursively for all users in the domain and checks if they are member of the given group).

这是得到一个组的所有成员的最佳方式,包括其子组?

Which is the best way to get all members of a group, including its subgroups?

推荐答案

以防万一,这可能有利于别人:这里是解决方案,我结束了。这仅仅是一个递归搜索,有一些额外的检查,以避免检查相同的组或用户的两倍,例如:如果A组B组是B组和成员是A组的成员或用户是多个组的成员。

Just in case this might benefit someone else: here is the solution I ended up with. It is just a recursive search, with some extra checks to avoid checking the same group or user twice, e.g. if groupA is member of groupB and groupB is member of groupA or a user is member of more than one group.

using System;
using System.DirectoryServices;
using System.Collections.Generic;

static class Program {

    static IEnumerable<SearchResult> GetMembers(DirectoryEntry searchRoot, string groupDn, string objectClass) {
        using (DirectorySearcher searcher = new DirectorySearcher(searchRoot)) {
            searcher.Filter = "(&(objectClass=" + objectClass + ")(memberOf=" + groupDn + "))";
            searcher.PropertiesToLoad.Clear();
            searcher.PropertiesToLoad.AddRange(new string[] { 
                "objectGUID",
                "sAMAccountName",
                "distinguishedName"});
            searcher.Sort = new SortOption("sAMAccountName", SortDirection.Ascending);
            searcher.PageSize = 1000;
            searcher.SizeLimit = 0;
            foreach (SearchResult result in searcher.FindAll()) {
                yield return result;
            }
        }
    }

    static IEnumerable<SearchResult> GetUsersRecursively(DirectoryEntry searchRoot, string groupDn) {
        List<string> searchedGroups = new List<string>();
        List<string> searchedUsers = new List<string>();
        return GetUsersRecursively(searchRoot, groupDn, searchedGroups, searchedUsers);
    }

    static IEnumerable<SearchResult> GetUsersRecursively(
        DirectoryEntry searchRoot,
        string groupDn,
        List<string> searchedGroups,
        List<string> searchedUsers) {
        foreach (var subGroup in GetMembers(searchRoot, groupDn, "group")) {
            string subGroupName = ((string)subGroup.Properties["sAMAccountName"][0]).ToUpperInvariant();
            if (searchedGroups.Contains(subGroupName)) {
                continue;
            }
            searchedGroups.Add(subGroupName);
            string subGroupDn = ((string)subGroup.Properties["distinguishedName"][0]);
            foreach (var user in GetUsersRecursively(searchRoot, subGroupDn, searchedGroups, searchedUsers)) {
                yield return user;
            }
        }
        foreach (var user in GetMembers(searchRoot, groupDn, "user")) {
            string userName = ((string)user.Properties["sAMAccountName"][0]).ToUpperInvariant();
            if (searchedUsers.Contains(userName)) {
                continue;
            }
            searchedUsers.Add(userName);
            yield return user;
        }
    }

    static void Main(string[] args) {
        using (DirectoryEntry searchRoot = new DirectoryEntry("LDAP://DC=x,DC=y")) {
            foreach (var user in GetUsersRecursively(searchRoot, "CN=MainGroup,DC=x,DC=y")) {
                Console.WriteLine((string)user.Properties["sAMAccountName"][0]);
            }
        }
    }

}

这篇关于C#,AD:得到一组的成员递归,即包括亚的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆