Получить список пользователей из Active Directory в данной группе AD
У меня есть код, который ищет всех пользователей в отделе:
string Department = "Billing";
DirectorySearcher LdapSearcher = new DirectorySearcher();
LdapSearcher.PropertiesToLoad.Add("displayName");
LdapSearcher.PropertiesToLoad.Add("cn");
LdapSearcher.PropertiesToLoad.Add("department");
LdapSearcher.PropertiesToLoad.Add("title");
LdapSearcher.PropertiesToLoad.Add("memberOf");
LdapSearcher.Filter = string.Format("(&(objectClass=user)(department={0}))", Department);
SearchResultCollection src = LdapSearcher.FindAll();
Как бы выглядел фильтр, если бы я хотел, чтобы все входили в группу AD "Только для чтения"?
Я все об этом ошибаюсь?
5 ответов
Глядя на ваш поиск, у меня есть пара моментов для вас. Во-первых, поиск использует objectClass (не индексируется) вместо objectCategory (индексируется). Огромная проблема производительности с этим запросом. Вы бы всегда хотели объединить их вместе в зависимости от того, что вы пытаетесь получить:
(&(objectCategory=person)(objectClass=user)) = All users (no contacts)
(&(objectCategory=person)(objectClass=contact)) = All contacts (no users)
(&(objectCategory=person)) = All users and contacts
Что касается поиска пользователей в группе, вы можете перечислить список объектов-членов определенной группы. В атрибуте member объекта group находится однозначное имя каждого пользователя.
Эта статья описывает перечисление членов группы...
Не забывайте, что вам, возможно, придется обрабатывать вложенные группы родительской группы, так как нет способа по умолчанию обрабатывать это с помощью запросов LDAP. Для этого вам может потребоваться оценить, является ли объект-член группой, а затем получить атрибут участника для этой дочерней группы.
Наконец, вы должны привыкнуть указывать префикс dns в своем запросе.
Без префикса DNS:
LDAP://ou=ouname,dc=domain,dc=com
С префиксом DNS (все три работают):
LDAP://servername/ou=ouname,dc=domain,dc=com
LDAP://servername.domain.com/ou=ouname,dc=domain,dc=com
LDAP://domain.com/ou=ouname,dc=domain,dc=com
Один домен не вызовет особых проблем, но когда вы попробуете выполнить поиск в среде с несколькими доменами, вы не получите этого дополнения. Надеюсь, это поможет вам приблизиться к вашей цели.
Я всегда находил Howto: (почти) все в Active Directory через C# помогает в большинстве вопросов AD.
Если вы уже знаете путь AD к группе, вероятно, было бы проще открыть на нем объект DirectoryEntry, а затем выполнить DirectorySearcher оттуда.
using (DirectoryEntry de = new DirectoryEntry("LDAP://somedomain/CN=FooBar"))
{
DirectorySearcher search = new DirectorySearcher(de, ("(objectClass=user)"));
}
Также в поисковике есть флаг для того, чтобы детализировать до субконтейнеров, я забыл название от руки.
Я использую следующий код (от http://blogs.technet.com/b/brad_rutkowski/archive/2008/04/15/c-getting-members-of-a-group-the-easy-way-with-net-3-5-discussion-groups-nested-recursive-security-groups-etc.aspx) это работает отлично.
IList<string> getMembers(string domainName, string groupName)
{
PrincipalContext ctx = new PrincipalContext(ContextType.Domain, domainName);
GroupPrincipal grp = GroupPrincipal.FindByIdentity(ctx, IdentityType.Name, groupName);
if (grp == null) {
throw new ApplicationException("We did not find that group in that domain, perhaps the group resides in a different domain?");
}
IList<string> members = new List<String>();
foreach (Principal p in grp.GetMembers(true))
{
members.Add(p.Name); //You can add more attributes, samaccountname, UPN, DN, object type, etc...
}
grp.Dispose();
ctx.Dispose();
return members;
}
//Search for Group and list group members
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.DirectoryServices.AccountManagement;
namespace ExportActiveDirectoryGroupsUsers
{
class Program
{
static void Main(string[] args)
{
if (args == null)
{
Console.WriteLine("args is null, useage: ExportActiveDirectoryGroupsUsers OutputPath"); // Check for null array
}
else
{
Console.Write("args length is ");
Console.WriteLine(args.Length); // Write array length
for (int i = 0; i < args.Length; i++) // Loop through array
{
string argument = args[i];
Console.Write("args index ");
Console.Write(i); // Write index
Console.Write(" is [");
Console.Write(argument); // Write string
Console.WriteLine("]");
}
try
{
using (var ServerContext = new PrincipalContext(ContextType.Domain, ServerAddress, Username, Password))
{
/// define a "query-by-example" principal - here, we search for a GroupPrincipal
GroupPrincipal qbeGroup = new GroupPrincipal(ServerContext, args[0]);
// create your principal searcher passing in the QBE principal
PrincipalSearcher srch = new PrincipalSearcher(qbeGroup);
// find all matches
foreach (var found in srch.FindAll())
{
GroupPrincipal foundGroup = found as GroupPrincipal;
if (foundGroup != null)
{
// iterate over members
foreach (Principal p in foundGroup.GetMembers())
{
Console.WriteLine("{0}|{1}", foundGroup.Name, p.DisplayName);
// do whatever you need to do to those members
}
}
}
}
//Console.WriteLine("end");
}
catch (Exception ex)
{
Console.WriteLine("Something wrong happened in the AD Query module: " + ex.ToString());
}
Console.ReadLine();
}
}
}
}