2010-09-08 4 views
7

eine Gruppe wie diese in Active Directory Gegeben:Holen Mitglieder einer Active Directory-Gruppe rekursiv, dh einschließlich der Untergruppen

MainGroup 
    GroupA 
    User1 
    User2 
    GroupB 
    User3 
    User4 

Ich kann leicht feststellen, ob User3 Mitglied des Maingroup oder eine ihrer Untergruppen mit Code wie folgt ist :

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); 
    } 
} 

Ich mag würde wissen, ob es eine ähnliche Art und Weise ist es, alle Benutzer zu erhalten, das Mitglied einer Gruppe oder einer ihrer Untergruppen, dh in dem Beispiel für Maingroup erhalten Benutzer1, Benutzer2, Benutzer3 und User4 .

Der offensichtliche Weg, alle Benutzer zu bekommen, besteht darin, jede Untergruppe rekursiv abzufragen, aber ich frage mich, ob es einen einfacheren Weg gibt.

Verwenden Sie den gleichen Ansatz mit dem Filter memberOf:1.2.840.113556.1.4.1941:, aber die Verwendung der Domain root anstelle des Benutzers als Suchbasis ist nicht möglich, da die Abfrage zu lange dauert (wahrscheinlich berechnet sie alle Gruppenmitgliedschaften rekursiv für alle Benutzer in der Domäne und überprüft, ob sie Mitglied der gegebenen Gruppe sind).

Welches ist der beste Weg, um alle Mitglieder einer Gruppe einschließlich ihrer Untergruppen zu bekommen?

Antwort

15

Nur für den Fall, dass dies jemand anderen nutzen könnte: Hier ist die Lösung, mit der ich endete. Es ist nur eine rekursive Suche mit einigen zusätzlichen Überprüfungen, um zu vermeiden, dass dieselbe Gruppe oder derselbe Benutzer zweimal überprüft wird, z. wenn groupA ein Mitglied von groupB und groupB ein Mitglied von groupA ist oder ein Benutzer Mitglied mehrerer Gruppen ist.

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]); 
      } 
     } 
    } 

} 
+0

Dieser Beitrag wurde für eine kleine Weile hier gewesen, aber ich wollte einen Dank für die Buchung Ihre Antwort hinzuzufügen. Ich bin gerade auf das gleiche Problem gestoßen, und ich versuche es gerade auszuprobieren. – Steven

+0

Ich weiß nicht, ob Sie das sehen werden (oder auch, wenn dies die geeignetste Art ist, eine Frage wie diese zu stellen, aber ich habe einige Probleme damit, dies zu erreichen, und ich denke, es liegt wahrscheinlich an meinem Mangel an Wenn ich den eindeutigen Namen (DN) meiner Gruppe erhalte, gibt es so etwas zurück: 'CN = , OU = , OU = Verteilerliste, OU = Exchange Services, OU = Core Directory Services, DC = , DC = com 'Aber wenn ich versuchte, dagegen zu suchen (oder das ohne das führende "CN ="), bekomme ich einen "unspezifizierten Fehler" an dem Punkt, wo Sucher durch FindAll() lief – Steven

+0

@Steven: Ich denke, dass der Das Beste für Sie wäre, eine neue Frage zu stellen (mit einem Link zu diesem, wenn es ein damit verbundenes Problem ist). Im Moment kann ich Ihnen nicht helfen, da ich eine Domain vermisse, an der ich testen kann, sorry :) –

1
static List<SearchResult> ad_find_all_members(string a_sSearchRoot, string a_sGroupDN, string[] a_asPropsToLoad) 
    { 
     using (DirectoryEntry de = new DirectoryEntry(a_sSearchRoot)) 
      return ad_find_all_members(de, a_sGroupDN, a_asPropsToLoad); 
    } 

    static List<SearchResult> ad_find_all_members(DirectoryEntry a_SearchRoot, string a_sGroupDN, string[] a_asPropsToLoad) 
    { 
     string sDN = "distinguishedName"; 
     string sOC = "objectClass"; 
     string sOC_GROUP = "group"; 
     string[] asPropsToLoad = a_asPropsToLoad; 
     Array.Sort<string>(asPropsToLoad); 
     if (Array.BinarySearch<string>(asPropsToLoad, sDN) < 0) 
     { 
      Array.Resize<string>(ref asPropsToLoad, asPropsToLoad.Length+1); 
      asPropsToLoad[asPropsToLoad.Length-1] = sDN; 
     } 
     if (Array.BinarySearch<string>(asPropsToLoad, sOC) < 0) 
     { 
      Array.Resize<string>(ref asPropsToLoad, asPropsToLoad.Length+1); 
      asPropsToLoad[asPropsToLoad.Length-1] = sOC; 
     } 

     List<SearchResult> lsr = new List<SearchResult>(); 

     using (DirectorySearcher ds = new DirectorySearcher(a_SearchRoot)) 
     { 
      ds.Filter = "(&(|(objectClass=group)(objectClass=user))(memberOf=" + a_sGroupDN + "))"; 
      //ds.PropertiesToLoad.Clear(); 
      ds.PropertiesToLoad.AddRange(asPropsToLoad); 
      //ds.PageSize = 1000; 
      //ds.SizeLimit = 0; 
      foreach (SearchResult sr in ds.FindAll()) 
       lsr.Add(sr); 
     } 

     for(int i=0;i<lsr.Count;i++) 
      if (lsr[i].Properties.Contains(sOC) && lsr[i].Properties[sOC].Contains(sOC_GROUP)) 
       lsr.AddRange(ad_find_all_members(a_SearchRoot, (string)lsr[i].Properties[sDN][0], asPropsToLoad)); 

     return lsr; 
    } 

    static void Main(string[] args) 
    { 
    foreach (var sr in ad_find_all_members("LDAP://DC=your-domain,DC=com", "CN=your-group-name,OU=your-group-ou,DC=your-domain,DC=com", new string[] { "sAMAccountName" })) 
     Console.WriteLine((string)sr.Properties["distinguishedName"][0] + " : " + (string)sr.Properties["sAMAccountName"][0]); 
    } 
Verwandte Themen