[英]Get users that are 'memberof' a group
我得到了一個可行的解決方案,但是我非常確定資源密集度較低的方法,因為當前的解決方案包括進行查詢以獲取組成員,然后查詢以獲取每個用戶的信息。
這是我的代碼:
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() );
}
理想情況下,我希望能夠執行單個查詢以獲取作為組成員的每個用戶,過濾要加載的屬性,然后顯示它們。 所以這樣的事情
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...
}
不幸的是,由於某些原因,這不起作用。
如果可以使用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);
}
}
我有一些VB代碼也會以舊的方式執行,但這對於AccountManagement來說肯定更簡單。
這是我所指的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
用法:
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
}
}
我最初使用的方法類似於您發布的方法,大約需要12分鍾才能完成整個公司的廣告並獲得結果。 切換到此方法后,大約需要2分鍾。 您需要使用我編寫ldapserver的ldapserver地址以及用戶ID和密碼,用戶名是您正在查找的人的SAMAccountName。
如果您在這里查看,您可以執行以下操作:
DirectoryEntry group = new DirectoryEntry("LDAP://CN=foo-group,DC=Cmp,DC=COM");
foreach(object dn in group.Properties["member"] )
//do whatever
使用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.