Get members of an Active Directory group recursively, i.e. including subgroups(递归获取 Active Directory 组的成员,即包括子组)
问题描述
在 Active Directory 中给定一个这样的组:
Given a group like this in Active Directory:
MainGroup
GroupA
User1
User2
GroupB
User3
User4
我可以使用如下代码轻松确定 User3 是否是 MainGroup 或其任何子组的成员:
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 的示例中获取 User1、User2、User3 和 User4.
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 is an easier way to do it.
对 memberOf:1.2.840.113556.1.4.1941:
过滤器使用相同的方法,但使用域根而不是用户作为搜索基础是不可行的,因为查询需要太多long(可能它会递归计算域中所有用户的所有组成员身份,并检查他们是否是给定组的成员).
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?
推荐答案
以防万一这可能对其他人有益:这是我最终得到的解决方案.这只是一个递归搜索,有一些额外的检查,以避免检查同一个组或用户两次,例如如果 groupA 是 groupB 的成员并且 groupB 是 groupA 的成员或者用户是多个组的成员.
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]);
}
}
}
}
这篇关于递归获取 Active Directory 组的成员,即包括子组的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持编程学习网!
本文标题为:递归获取 Active Directory 组的成员,即包括子组
基础教程推荐
- 从 VB6 迁移到 .NET/.NET Core 的最佳策略或工具 2022-01-01
- 覆盖 Json.Net 中的默认原始类型处理 2022-01-01
- 当键值未知时反序列化 JSON 2022-01-01
- Page.OnAppearing 中的 Xamarin.Forms Page.DisplayAlert 2022-01-01
- 使用 SED 在 XML 标签之间提取值 2022-01-01
- 创建属性设置器委托 2022-01-01
- C# - 将浮点数转换为整数...并根据余数更改整数 2022-01-01
- 如何使用OpenXML SDK将Excel转换为CSV? 2022-01-01
- 我什么时候应该使用 GC.SuppressFinalize()? 2022-01-01
- C# - 如何列出发布到 ASPX 页面的变量名称和值 2022-01-01