[英]Get users that are 'memberof' a group
I got a working solution, however I'm pretty sure there is a less resource-intensive method because the current solution involves doing a query to get the groups member and then a query to get each users information. 我得到了一个可行的解决方案,但是我非常确定资源密集度较低的方法,因为当前的解决方案包括进行查询以获取组成员,然后查询以获取每个用户的信息。
Here is the code I have : 这是我的代码:
DirectoryEntry root = new DirectoryEntry( "LDAP://server:port" );
DirectorySearcher searcher = new DirectorySearcher( root );
searcher.Filter = "(&(ObjectClass=Group)(CN=foo-group))";
var members = (IEnumerable)searcher.FindOne()
.GetDirectoryEntry()
.Invoke( "members" );
Dictionary<string , string> results = new Dictionary<string , string>();
foreach( object member in members ) {
DirectoryEntry de = new DirectoryEntry( member );
results.Add( de.Properties[ "SAMAccountname" ][ 0 ].ToString(), de.Properties[ "cn" ][ 0 ].ToString() );
}
Ideally I'd like to be able to do a single query to get every user that are member of a group, filters the properties to load and then display them. 理想情况下,我希望能够执行单个查询以获取作为组成员的每个用户,过滤要加载的属性,然后显示它们。 So something like this 所以这样的事情
DirectoryEntry root = new DirectoryEntry( "LDAP://server:port" );
DirectorySearcher searcher = new DirectorySearcher( root );
searcher.PropertiesToLoad.Add( "cn" );
searcher.PropertiesToLoad.Add( "SAMAccountname" );
searcher.Filter = "(&(ObjectClass=user)(memberof=foo-group))";
foreach( var user in searcher.FindAll() ) {
//do whatever...
}
Unfortunately, that doesn't work for some reason. 不幸的是,由于某些原因,这不起作用。
If you can use System.DirectoryServices.AccountManagement
: 如果可以使用System.DirectoryServices.AccountManagement
:
var context = new PrincipalContext(ContextType.Domain, "YOUR_DOMAIN_NAME");
using (var searcher = new PrincipalSearcher())
{
var groupName = "YourGroup";
var sp = new GroupPrincipal(context, groupName);
searcher.QueryFilter = sp;
var group = searcher.FindOne() as GroupPrincipal;
if (group == null)
Console.WriteLine("Invalid Group Name: {0}", groupName);
foreach (var f in group.GetMembers())
{
var principal = f as UserPrincipal;
if (principal == null || string.IsNullOrEmpty(principal.Name))
continue;
Console.WriteLine("{0}", principal.Name);
}
}
I have some VB code that'll do it the old way also, but this is definitely simpler with AccountManagement. 我有一些VB代码也会以旧的方式执行,但这对于AccountManagement来说肯定更简单。
Here's the VB code I was referring to (again it isn't pretty but it's functional): 这是我所指的VB代码(再次它不漂亮,但它的功能):
Public Function GetUsersByGroup(de As DirectoryEntry, groupName As String) As IEnumerable(Of DirectoryEntry)
Dim userList As New List(Of DirectoryEntry)
Dim group As DirectoryEntry = GetGroup(de, groupName)
If group Is Nothing Then Return Nothing
For Each user In GetUsers(de)
If IsUserInGroup(user, group) Then
userList.Add(user)
End If
Next
Return userList
End Function
Public Function GetGroup(de As DirectoryEntry, groupName As String) As DirectoryEntry
Dim deSearch As New DirectorySearcher(de)
deSearch.Filter = "(&(objectClass=group)(SAMAccountName=" & groupName & "))"
Dim result As SearchResult = deSearch.FindOne()
If result Is Nothing Then
Return Nothing
End If
Return result.GetDirectoryEntry()
End Function
Public Function GetUsers(de As DirectoryEntry) As IEnumerable(Of DirectoryEntry)
Dim deSearch As New DirectorySearcher(de)
Dim userList As New List(Of DirectoryEntry)
deSearch.Filter = "(&(objectClass=person))"
For Each user In deSearch.FindAll()
userList.Add(user.GetDirectoryEntry())
Next
Return userList
End Function
Public Function IsUserInGroup(user As DirectoryEntry, group As DirectoryEntry) As Boolean
Dim memberValues = user.Properties("memberOf")
If memberValues Is Nothing OrElse memberValues.Count = 0 Then Return False
For Each g In memberValues.Value
If g = group.Properties("distinguishedName").Value.ToString() Then
Return True
End If
Next
Return False
End Function
And usage: 用法:
Dim entries = New DirectoryEntry("LDAP://...")
Dim userList As IEnumerable(Of DirectoryEntry) = GetUsersByGroup(entries, "GroupName")
using System.DirectoryServices;
DirectoryEntry objEntry = DirectoryEntry(Ldapserver, userid, password);
DirectorySearcher personSearcher = new DirectorySearcher(objEntry);
personSearcher.Filter = string.Format("(SAMAccountName={0}", username);
SearchResult result = personSearcher.FindOne();
if(result != null)
{
DirectoryEntry personEntry = result.GetDirectoryEntry();
PropertyValueCollection groups = personEntry.Properties["memberOf"];
foreach(string g in groups)
{
Console.WriteLine(g); // will write group name
}
}
I originally used a method similar to what you have posted and it took about 12 minutes to run through my entire company's AD and get the results. 我最初使用的方法类似于您发布的方法,大约需要12分钟才能完成整个公司的广告并获得结果。 After switching to this method, it takes about 2 minutes. 切换到此方法后,大约需要2分钟。 You will need to use the ldapserver address where I wrote ldapserver and the userid and password as well and username is the SAMAccountName for the person you're looking up. 您需要使用我编写ldapserver的ldapserver地址以及用户ID和密码,用户名是您正在查找的人的SAMAccountName。
It's shorter using GroupPrincipal
method FindByIdentity
which gives also multiple ways to identify the group with IdentityType
: 使用GroupPrincipal
方法FindByIdentity
更短, GroupPrincipal
提供了使用IdentityType
标识组的多种方法:
using (var context = new PrincipalContext(ContextType.Domain, "YOUR_DOMAIN_NAME")
{
var userPrincipals = GroupPrincipal
.FindByIdentity(context, IdentityType.SamAccountName, "GROUP_ACCOUNT")
.GetMembers(true) // recursive
.OfType<UserPrincipal>();
...
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.