2010-09-08 30 views
7

Cho một nhóm như thế này trong Active Directory:Nhận các thành viên của một nhóm Active Directory đệ quy, tức là bao gồm các phân nhóm

MainGroup 
    GroupA 
    User1 
    User2 
    GroupB 
    User3 
    User4 

tôi có thể dễ dàng xác định nếu User3 là thành viên của MainGroup hoặc bất kỳ phân nhóm của mình với mã như thế này :

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

tôi muốn biết nếu có một cách tương tự để có được tất cả những người dùng là thành viên của một nhóm hoặc bất kỳ phân nhóm của nó, tức là trong ví dụ cho MainGroup được User1, User2, User3 và User4 .

Cách rõ ràng để thu hút tất cả người dùng là truy vấn đệ quy từng nhóm con, nhưng tôi đã tự hỏi liệu có cách nào dễ dàng hơn không.

Sử dụng cùng một cách tiếp cận với bộ lọc memberOf:1.2.840.113556.1.4.1941:, nhưng sử dụng tên miền gốc thay vì người dùng làm cơ sở tìm kiếm là không khả thi, vì truy vấn mất quá nhiều thời gian (có thể tính toán tất cả các thành viên nhóm đệ quy cho tất cả người dùng trong và kiểm tra nếu họ là thành viên của nhóm đã cho).

Cách tốt nhất để có được tất cả thành viên của một nhóm, bao gồm các nhóm con của nhóm là ai?

Trả lời

15

Chỉ trong trường hợp điều này có thể có lợi cho người khác: đây là giải pháp mà tôi đã kết thúc. Đây chỉ là tìm kiếm đệ quy, với một số kiểm tra bổ sung để tránh kiểm tra cùng một nhóm hoặc người dùng hai lần, ví dụ: nếu groupA là thành viên của groupB và groupB là thành viên của groupA hoặc người dùng là thành viên của nhiều nhóm.

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

Chủ đề này đã được ở đây một thời gian ngắn, nhưng tôi muốn thêm một nhờ gửi bài cho câu trả lời của bạn. Tôi vừa mới gặp phải vấn đề tương tự, và tôi sắp thử điều này. – Steven

+0

Tôi không biết nếu bạn sẽ thấy điều này (hoặc thậm chí nếu đây là cách thích hợp nhất để hỏi một câu hỏi như thế này, nhưng tôi đang gặp một số vấn đề để làm việc này, và tôi nghĩ đó có thể là do tôi thiếu Khi tôi nhận được tên riêng biệt (DN) của nhóm của tôi, nó trả về một cái gì đó như thế này: 'CN = , OU = , OU = Danh sách phân phối, OU = Exchange Services, OU = Dịch vụ thư mục lõi, DC = , DC = com 'Nhưng khi tôi cố gắng để chống lại điều đó (hoặc rằng không có "CN =" hàng đầu), tôi nhận được một "Lỗi không xác định" tại điểm mà người tìm kiếm lặp qua FindAll() – Steven

+0

@Steven: Tôi nghĩ rằng tốt nhất cho bạn sẽ được đăng một câu hỏi mới (với một liên kết đến này nếu nó là một vấn đề liên quan). Ngay bây giờ tôi không thể giúp bạn, như tôi đang thiếu một tên miền để kiểm tra, xin lỗi :) –

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]); 
    } 
Các vấn đề liên quan