从多个林环境中获取Domain Local Group的所有成员

我有一个域本地组,它是林A中域A的一部分。

我试图迭代这个组中的所有成员。 它迭代遍历林A的所有域,但不会迭代域B中的任何组成员,在林B中。

是从不同的森林开始迭代相同代码的唯一方法吗?

我们已尝试使用System.DirectoryServices.AccountManagement类,但它们和Windows Server 2012域控制器似乎存在问题。

 private List getUsersInGroup(string groupDN) { var users = new List(); 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; } 

预先感谢您的帮助。

您将无法使用memberOf属性搜索其他林中的组成员,因为当您将用户添加到属于另一个林的域本地组时,它不会被设置。

相反,AD在组的域中创建一个类型为ForeignSecurityPrincipal的对象,该组具有目标用户的SID作为其CN 。 然后,该对象的DN将添加到组的成员属性中。

不幸的是,与用户对象不同, foreingSecurityPrincipal对象永远不会获得memberOf属性,因此即使删除objectType条件,搜索也无法找到它们。

所以,你真的应该反转你的搜索并按照rufanov的建议枚举该组的成员属性。

但是您还应该扩展代码以处理这些外部安全主体。 要检测DirectoryEntry是否表示外部主体,可以检查其对象类是否包含foreignSecurityPricipal 。 如果是,则CN属性将包含可用于按objectSid属性搜索的SID

 if (de.Properties["objectClass"].Contains("foreignSecurityPrincipal")) { // use this value in a search condition for objectSid var sidString = de.Properties["cn"].Cast().First(); IdentityReference id = new SecurityIdentifier(sid); var account = id.Translate(typeof(NTAccount)).ToString().Split('\\'); var userName = account[1]; var domainName = account[0]; } 

为什么不能只枚举目标组的成员,而不是为具有目标组作为“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 GetMembersOf(string groupdn) { var context = new DirectoryContext(DirectoryContextType.Forest); var Result = new List(); 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; } } }