2013-12-18 62 views
3

我有一個域本地組是域A在森林A的部分獲得來自域本地組所有成員橫跨多林環境

我想重複這個組中的所有成員。它迭代遍歷所有森林A的域,但不會遍歷域B中森林B中的任何組成員。

從不同森林中開始迭代相同代碼的唯一方法是什麼?

我們嘗試使用System.DirectoryServices.AccountManagement類,但似乎存在與它們和Windows Server 2012域控制器有關的問題。

private List<User> getUsersInGroup(string groupDN) 
    { 
     var users = new List<User>(); 

     using (DirectoryEntry de = new DirectoryEntry("GC://rootDSE")) 
     { 
      var rootName = de.Properties["rootDomainNamingContext"].Value.ToString(); 
      using (var userBinding = new DirectoryEntry("GC://" + rootName)) 
      { 
       using (DirectorySearcher adSearch = new DirectorySearcher(userBinding)) 
       { 
        adSearch.ReferralChasing = ReferralChasingOption.All; 
        adSearch.Filter = String.Format("(&(memberOf={0})(objectClass=person))", groupDN); 
        adSearch.PropertiesToLoad.Add("distinguishedName"); 
        adSearch.PropertiesToLoad.Add("givenname"); 
        adSearch.PropertiesToLoad.Add("samaccountname"); 
        adSearch.PropertiesToLoad.Add("sn"); 
        adSearch.PropertiesToLoad.Add("title"); 
        adSearch.PropertiesToLoad.Add("displayName"); 
        adSearch.PropertiesToLoad.Add("department"); 

        using (var searchResults = adSearch.FindAll()) 
        { 
         foreach (SearchResult result in searchResults) 
         { 
          User u = new User(); 

          u.UserName = result.Properties["samaccountname"][0].ToString(); 
          u.DistinguishedName = result.Properties["distinguishedName"][0].ToString(); 
          if (result.Properties.Contains("title")) 
          { 
           u.Title = result.Properties["title"][0].ToString(); 
          } 

          if (result.Properties.Contains("department")) 
          { 
           u.Department = result.Properties["department"][0].ToString(); 
          } 

          if (result.Properties.Contains("displayName")) 
          { 
           u.DisplayName = result.Properties["displayName"][0].ToString(); 
          } 
          u.DomainName = getDomainFromDN(u.DistinguishedName); 


          users.Add(u); 
         } 
        } 
       } 


      } 
     } 


     return users; 
    } 

非常感謝您的幫助。

+0

兩點搜索SID:(1)你說:「通過迭代的唯一方法相同的代碼從不同的森林開始?「 - 這是否意味着這種方法適合你?如果確實如此,你不喜歡那種方法? (2)你說過「我們已經嘗試過使用System.DirectoryServices。AccountManagement'類,但是他們和Windows Server 2012域控制器似乎存在問題。「遇到了什麼問題? – Nathan

回答

2

您將無法使用的memberOf屬性搜索組成員在不同的林中,因爲它只是沒有設置你的時候將用戶添加到屬於另一個林的域本地組。

相反,AD中創建具有目標用戶的SID作爲其CN組的域類型ForeignSecurityPrincipal的對象。然後該對象的DN被添加到該組的成員屬性中。

不幸的是,不像用戶對象,foreingSecurityPrincipal對象從來沒有得到的memberOf屬性,所以你的搜索不會找到他們,即使你刪除的objectType條件。

所以,你真的應該扭轉你的搜索並列舉rufanov建議的團體的成員財產。

但是您還應該擴展代碼以處理這些外部安全主體。若要檢測您的DirectoryEntry是否表示外部主體,則可以檢查其對象類是否包含foreignSecurityPricipal。如果是這樣,CN屬性將包含您可以使用的objectSID財產澄清

if (de.Properties["objectClass"].Contains("foreignSecurityPrincipal")) 
{ 
    // use this value in a search condition for objectSid 
    var sidString = de.Properties["cn"].Cast<string>().First(); 

    IdentityReference id = new SecurityIdentifier(sid); 

    var account = id.Translate(typeof(NTAccount)).ToString().Split('\\'); 

    var userName = account[1]; 
    var domainName = account[0]; 
} 
+1

這就是我所缺少的 - 同時使用*成員*而不是* memberOf * - 感謝您的幫助!更新您的帖子以顯示如何提取行事域名並從sid登錄。 –

1

爲什麼您不能僅枚舉目標組的成員,而不是搜索整個目錄組爲「memberof」屬性值之一的用戶?與使用DirectorySearcher完成此任務相比,它可以更快更簡單。組「成員」屬性在整個森林範圍內,因此它將包含來自森林中任何域的成員。

代碼獲取用戶的集合可能是這樣的:

using System.Collections; 
using System.Collections.Generic; 
using System.DirectoryServices; 
using System.DirectoryServices.ActiveDirectory; 
using System.Linq; 

namespace AdTest 
{ 
    class Program 
    { 
     static void Main(string[] args) 
     { 
      var p = new Program(); 
      var users = p.GetMembersOf("LDAP://CN=SQL Adminsistrators,OU=_System accounts and groups,OU=Domain Users,DC=test,DC=net"); 
      // do something with users 
     } 

     private List<User> GetMembersOf(string groupdn) 
     { 
      var context = new DirectoryContext(DirectoryContextType.Forest); 
      var Result = new List<User>(); 
      var GroupEntity = new DirectoryEntry(groupdn); 
      var Members = (IEnumerable)GroupEntity.Invoke("Members", null); 

      foreach (var member in Members) 
      { 
       var UserEntry = new DirectoryEntry(member); 
       var User = GetUser(UserEntry); 

       if(User != null) 
        Result.Add(User); 
      } 


      return Result; 

     } 

     private User GetUser(DirectoryEntry UserEntry) 
     { 
      var Result = new User(); 

      foreach (PropertyValueCollection UserProperty in UserEntry.Properties) 
      { 
       switch (UserProperty.PropertyName) 
       { 
        case "sAMAccountName": 
         Result.UserName = (string)UserProperty.Value; 
         break; 
        case "distinguishedName": 
         Result.DistinguishedName = (string)UserProperty.Value; 
         Result.DomainName = getDomainFromDN((string)UserProperty.Value); 
         break; 
        case "title": 
         Result.Title = (string)UserProperty.Value; 
         break; 
        case "department": 
         Result.Department = (string)UserProperty.Value; 
         break; 
        case "displayName": 
         Result.DisplayName = (string)UserProperty.Value; 
         break; 
        case "objectClass": 
         var UserClasses = (object[])UserProperty.Value; 

         if (UserClasses.Contains("user")) 
          break; 
         else 
          return null; 

        default: 
         break; 
       } 
      } 
      return Result; 
     } 

     private string getDomainFromDN(string p) 
     { 
      return string.Empty; 
     } 

     public string groupDN { get; set; } 
    } 
} 
+0

使用此代碼時,我收到」未指定的錯誤「,因爲DirectoryEntry GroupEntity未綁定到任何目錄服務(根本沒有引用'context'變量) –

+0

實際上,** DirectorySearcher **比獲得** DirectoryEntry **實例要快得多,因爲當你指定你想讓搜索者獲得哪些屬性時確保你只是獲得這些屬性**另一方面,DirectoryEntry **獲取所有屬性,並且需要相當長的一段時間,我實際上必須重寫我們的代碼,使用** DirectoryEntry **到** DirectorySearcher/SearchResult **爲了提高性能, –