【发布时间】:2018-03-06 17:48:29
【问题描述】:
问题:如何以一致的方式检索所有组成员?
上下文:我正在检索人、组、联系人或计算机的所有对象:
Filter = "(|(objectCategory=person)(objectCategory=computer)(objectCategory=group))"
我现在需要检索组的所有成员。我已经开发了三种方法来做到这一点;但是,他们为同一组返回不同的结果,我不知道为什么。我怀疑它可能是由嵌套组(即组内组)引起的。调试它是一个挑战,因为某些组包含太多成员,以至于调试器超时并且没有显示任何结果。
方法 1 和 2 很慢。方法3很快。所以,我更喜欢使用方法3。
Group Name Retrieval Method Recursive Search Count Members Comment
Group1 AccountManagement TRUE 505
Group1 AccountManagement FALSE 505
Group1 DirectoryServices N/A 101
Group2 AccountManagement TRUE 440 Contains group name 'Group3'
Group2 AccountManagement FALSE 440 Contains group name 'Group3'
Group2 DirectoryServices N/A 100 Contains group name 'Group3'
Group3 AccountManagement TRUE 101 All Group3
Group3 AccountManagement FALSE 2 All Group3
Group3 DirectoryServices N/A 2 1 user 1 group (Group2)
方法1和2:使用S.DS.AM获取组成员,其中GetMembers()分别设置为true或false:https://msdn.microsoft.com/en-us/library/system.directoryservices.accountmanagement(v=vs.110).aspx
private static List<Guid> GetGroupMemberList(string strPropertyValue, string strDomainController, bool bolRecursive)
{
List<Guid> listGroupMemberGuid = null;
GroupPrincipal groupPrincipal = null;
PrincipalSearchResult<Principal> listPrincipalSearchResult = null;
List<Principal> listPrincipalNoNull = null;
PrincipalContext principalContext = null;
ContextType contextType;
IdentityType identityType;
try
{
listGroupMemberGuid = new List<Guid>();
contextType = ContextType.Domain;
principalContext = new PrincipalContext(contextType, strDomainController);
identityType = IdentityType.Guid;
groupPrincipal = GroupPrincipal.FindByIdentity(principalContext, identityType, strPropertyValue);
if (groupPrincipal != null)
{
listPrincipalSearchResult = groupPrincipal.GetMembers(bolRecursive);
listPrincipalNoNull = listPrincipalSearchResult.Where(item => item.Name != null).ToList();
foreach (Principal principal in listPrincipalNoNull)
{
listGroupMemberGuid.Add((Guid)principal.Guid);
}
}
return listGroupMemberGuid;
}
catch (MultipleMatchesException)
{
throw new MultipleMatchesException(strPropertyValue);
}
catch (Exception ex)
{
throw ex;
}
finally
{
listGroupMemberGuid = null;
listPrincipalSearchResult.Dispose();
principalContext.Dispose();
groupPrincipal.Dispose();
}
}
方法3:使用S.DS.AD获取群组成员:https://msdn.microsoft.com/en-us/library/system.directoryservices.activedirectory(v=vs.110).aspx
private static List<string> GetGroupMemberList(string strPropertyValue, string strActiveDirectoryHost, int intActiveDirectoryPageSize)
{
List<string> listGroupMemberDn = new List<string>();
string strPath = strActiveDirectoryHost + "/<GUID=" + strPropertyValue + ">";
DirectoryEntry directoryEntryGroup;
DirectoryEntry directoryEntryGroupMembers;
DirectorySearcher directorySearcher;
SearchResultCollection searchResultCollection;
DataTypeConverter objConverter = null;
objConverter = new DataTypeConverter();
try
{
directoryEntryGroup = new DirectoryEntry(strPath, null, null, AuthenticationTypes.Secure);
directoryEntryGroup.RefreshCache();
}
catch (Exception ex)
{
throw ex;
}
try
{
directorySearcher = new DirectorySearcher(directoryEntryGroup)
{
//Filter = "(objectCategory=group)", // Group
SearchScope = SearchScope.Subtree,
PageSize = intActiveDirectoryPageSize,
};
directorySearcher.PropertiesToLoad.Add("objectGUID");
searchResultCollection = directorySearcher.FindAll();
}
catch (Exception ex)
{
throw ex;
}
try
{
foreach (SearchResult searchResult in searchResultCollection)
{
directoryEntryGroupMembers = searchResult.GetDirectoryEntry();
foreach (object objGroupMember in directoryEntryGroupMembers.Properties["member"])
{
listGroupMemberDn.Add((string)objGroupMember);
}
}
return listGroupMemberDn;
}
catch (Exception ex)
{
throw ex;
}
finally
{
listGroupMemberDn = null;
strPath = null;
directoryEntryGroup.Dispose();
directoryEntryGroupMembers = null;
directorySearcher.Dispose();
searchResultCollection.Dispose();
objConverter = null;
}
}
方法4:(循环与GetNextChunk()方法实现)
private static List<string> GetGroupMemberList(string strPropertyValue, string strActiveDirectoryHost, int intActiveDirectoryPageSize)
{
// Variable declaration(s).
List<string> listGroupMemberDn = new List<string>();
string strPath = strActiveDirectoryHost + "/<GUID=" + strPropertyValue + ">";
string strMemberPropertyRange = null;
DirectoryEntry directoryEntryGroup = null;
DirectorySearcher directorySearcher = null;
SearchResultCollection searchResultCollection = null;
// https://msdn.microsoft.com/en-us/library/windows/desktop/ms676302(v=vs.85).aspx
const int intIncrement = 1500;
// Load the DirectoryEntry.
try
{
// Setup a secure connection with Active Directory (AD) using Kerberos by setting the directoryEntry with AuthenticationTypes.Secure.
directoryEntryGroup = new DirectoryEntry(strPath, null, null, AuthenticationTypes.Secure);
// Load the property values for this DirectoryEntry object into the property cache.
directoryEntryGroup.RefreshCache();
}
catch (Exception)
{ }
#region Method1
// Enumerate group members.
try
{
// Check to see if the group has any members.
if (directoryEntryGroup.Properties["member"].Count > 0)
{
int intStart = 0;
while (true)
{
// End of the range.
int intEnd = intStart + intIncrement - 1;
strMemberPropertyRange = string.Format("member;range={0}-{1}", intStart, intEnd);
directorySearcher = new DirectorySearcher(directoryEntryGroup)
{
// Set the Filter criteria that is used to constrain the search within AD.
Filter = "(|(objectCategory=person)(objectCategory=computer)(objectCategory=group))", // User, Contact, Group, Computer objects
// Set the SearchScope for how the AD tree is searched (Default = Subtree).
SearchScope = SearchScope.Base,
// The PageSize value should be set equal to the PageSize that is set by the AD administrator (Default = 0).
PageSize = intActiveDirectoryPageSize,
PropertiesToLoad = { strMemberPropertyRange }
};
try
{
// Populate the searchResultCollection with all records within AD that match the Filter criteria.
searchResultCollection = directorySearcher.FindAll();
foreach (SearchResult searchResult in searchResultCollection)
{
var membersProperties = searchResult.Properties;
var membersPropertyNames = membersProperties.PropertyNames.OfType<string>().Where(n => n.StartsWith("member;"));
foreach (var propertyName in membersPropertyNames)
{
// Get all members from the ranged result.
var members = membersProperties[propertyName];
foreach (string memberDn in members)
{
// Add the member's "distinguishedName" attribute value to the list.
listGroupMemberDn.Add(memberDn);
}
}
}
}
catch (DirectoryServicesCOMException)
{
// When the start of the range exceeds the number of available results, an exception is thrown and we exit the loop.
break;
}
// Increment for the next range.
intStart += intIncrement;
}
}
// return the listGroupMemberDn;
return listGroupMemberDn;
}
#endregion
finally
{
// Cleanup objects.
listGroupMemberDn = null;
strPath = null;
strMemberPropertyRange = null;
directoryEntryGroup.Dispose();
directorySearcher.Dispose();
searchResultCollection.Dispose();
}
}
【问题讨论】:
标签: c# sql-server active-directory ldap ldap-query