在 Active Directory 中给定这样一个组:
MainGroup
GroupA
User1
User2
GroupB
User3
User4
我可以使用如下代码轻松确定 User3 是否是 MainGroup 或其任何子组的成员:
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。
获取所有用户的明显方法是递归查询每个子组,但我想知道是否有更简单的方法来做到这一点。
使用与 memberOf:1.2.840.113556.1.4.1941:
过滤器相同的方法,但是使用域根而不是用户作为搜索基础是不可行的,因为查询需要太多long(可能它为域中的所有用户递归地计算所有组成员资格,并检查他们是否是给定组的成员)。
获取群组(包括其子群组)的所有成员的最佳方式是什么?
最佳答案
以防万一这可能使其他人受益:这是我最终得到的解决方案。这只是一个递归搜索,有一些额外的检查以避免检查同一个组或用户两次,例如如果 groupA 是 groupB 的成员,groupB 是 groupA 的成员,或者用户是多个组的成员。
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# - 递归地获取 Active Directory 组的成员,即包括子组,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/3665487/