C# LDAP 查询以获取特定组中用户的管理员

C# LDAP Query to Get Managers of users in certain groups

我目前编写了一个 c# 脚本来检索属于三个独立用户组的用户 - 看起来像这样...

string DomainPath = "LDAP://DC=<dc>,DC=<dc>,DC=org";
DirectoryEntry searchRoot = new DirectoryEntry(DomainPath); 
DirectorySearcher search = new DirectorySearcher(searchRoot);
search.Filter = "(&(objectClass=user)(objectCategory=person)(|(memberof=CN=group1,OU=Groups,OU=<ou>,DC=dc,DC=<dc>,DC=org)(memberof=CN=group2,OU=Groups,OU=<ou>,DC=<dc>,DC=<dc>,DC=org)(memberof=CN=group3,OU=Groups,OU=<ou>,DC=<dc>,DC=<dc>,DC=org)))";
search.PropertiesToLoad.Add("samaccountname");
search.PropertiesToLoad.Add("mail");
search.PropertiesToLoad.Add("usergroup");
search.PropertiesToLoad.Add("displayname");
search.PropertiesToLoad.Add("manager");
SearchResult result;
SearchResultCollection resultCol = search.FindAll();

使用此代码,我能够检索为该用户公开的任何属性,包括 "manager" 记录。经理记录在此级别公开为 DN:

Manager = "CN=MTK93,OU=Users,OU=<ou>,DC=<dc>,DC=<dc>,DC=org"

真正想要的是能够递归地获取现有查询返回的每个经理的所有用户属性 - 然后将它们组合成一个数据集...

例如,考虑以下层次结构....

Lisa (manager's manager)
   | 
   | -- Tim (Manager)
   |    mail = tim@a.com, usergroup = groupA, manager = Lisa
   |     | 
   |     |-- Mike
   |     |    mail = mike@a.com, usergroup = group1, manager = Tim
   |     |-- Lori
   |     |    mail = lori@a.com, usergroup = group2, manager = Tim
   | -- Katie (another manager)
         |    mail = katie@a.com, usergroup = groupB, manager = Lisa
         |
         |-- John
         |    mail = john@a.com, usergroup = group3, manager = Katie
         |-- Larry
              mail = larry@a.com, usergroup = group4, manager = Katie

我的查询返回 mike、lori、katie 和 john,因为他们存在于我要查询的组(group1、group2、group3)中 - 但我也需要 Tim 和 Katie 的用户记录(因为他们是属于这些群体的人)

理想的输出看起来像这样...

Name       Mail        Group        Manager
------------------------------------------------
Mike     mike@a.com   group1        Tim's DN
Lori     lori@a.com   group2        Tim's DN
John     john@a.com   group3        Katie's DN
Katie    katie@a.com  groupB        Lisa's DN
Tim      time@a.com   groupA        Lisa's DN

注意:我不想要 Lisa(她下面的级别没有人属于 group1、group2 或 group3)或 Larry(不属于 group1、group2 或 group3)

事实证明,这个 LDAP 查询的递归性质很难理解。

我通过以下方法获得了我需要的结果:

  1. 使用组动态构建 LDAP 查询
  2. 使用自定义函数将组 1、组 2 和组 3 中的用户加载到列表中
  3. 使用 Linq 从组 1、2 和 3 中的结果用户列表中获取不同的经理列表
  4. 使用管理器的可分辨名称动态构建另一个 LDAP 查询
  5. 将经理记录加载到另一个列表中并与原始用户列表合并
  6. 删除所有重复项

    // class variable
    List<ActiveDirectoryUser> recordsToInsert;
    
    // build the query appender
    string queryAppender = "";
    foreach (string activeDirectoryGroup in activeDirectoryGroups)
    {
        queryAppender += "(memberof=CN=" + activeDirectoryGroup + ",OU=Groups,OU=<<ou>>,DC=<<dc>>,DC=<<dc>>,DC=<org>>)";
    }
    
    // create the ldap query string
    var ldapQueryForUsersInDtGroups = "(&(objectClass=user)(objectCategory=person)(|" + queryAppender + "))";
    
    // first get the users that belong to the active directory groups...
    recordsToInsert = getEmployeeRecordsFromLdapQuery(ldapQueryForUsersInDtGroups);
    
    // then, query again to make sure we are including the managers for the people returned from the first query
    var distinctManagers = (from record in recordsToInsert select record.manager).Distinct();
    
    // build an ldap query to get only the records for the managers we need
    // example query string with 2 managers: 
    // (&(objectClass=user)(objectCategory=person)
    
    queryAppender = "";
    foreach (var manager in distinctManagers)
    {
        queryAppender += "(distinguishedName=" + manager + ")";
    }
    
    // ldap query filter for the managers
    var ldapQueryForManagers = "(&(objectClass=user)(objectCategory=person)(|" + queryAppender + "))";
    
    // combine the result set with the managers result set
    recordsToInsert.AddRange(getEmployeeRecordsFromLdapQuery(ldapQueryForManagers));
    
    // filter off any duplicates.
    uniqueRecordsToInsert = recordsToInsert.GroupBy(x => x.employeeId).Select(x => x.First()).ToList<ActiveDirectoryUser>();