С# Запрос Active Directory с пользовательским свойством в .NET Standard 2.0

Как я могу запросить Active Directory моей компании с пользовательским свойством в .NET Standard2.0? Например, если я хочу сделать запрос с заданным свойством, мой код будет выглядеть так:

FSharpOption<UserPrincipal> TryGetUser(SecurityIdentifier sid)
{
    using (var context = new PrincipalContext(ContextType.Domain))
    {
        var user = UserPrincipal.FindByIdentity(context, IdentityType.Sid, sid.Value);
        if (user == null)
            return FSharpOption<UserPrincipal>.None;

        return FSharpOption<UserPrincipal>.Some(user);
    }
}

Теперь я хочу запросить пользовательское свойство с именем "manager", которое является строкой. Я хочу найти всех пользователей, имеющих manager == "...".


person Moritz Großmann    schedule 22.02.2019    source источник
comment
Я почти уверен, что для этого вам придется создать собственный строковый фильтр. это будет выглядеть примерно так (&(objectClass=person)(objectClass=user))   -  person Salim Proctor    schedule 22.02.2019
comment
На самом деле вы можете расширить класс UserPrincipal, чтобы сделать это (вместе с переопределением методов Find). См. ТАК здесь   -  person PBMe_HikeIt    schedule 27.04.2020


Ответы (1)


Вы не можете сделать это с помощью UserPrincipal, а PrincipalSearcher позволит вам искать только по свойствам, предоставленным UserPrincipal. Вы должны использовать DirectorySearcher напрямую (что и PrincipalSearcher все равно использует за кулисами).

Вот пример того, что вы могли бы сделать:

public IEnumerable<string> GetUsersWithManager(string managerDn) {
    var search = new DirectorySearcher(new DirectoryEntry()) {
        Filter = $"(&(objectClass=user)(manager={managerDn}))"
    };
    search.PropertiesToLoad.Add("distinguishedName");

    using (var results = search.FindAll()) {
        foreach (SearchResult result in results) {
            if (result.Properties.Contains("mail")) {
                yield return (string) result.Properties["distinguishedName"][0];
            }
        }
    }
}

Параметр представляет собой distinguishedName менеджера и возвращает distinguishedName всех пользователей, у которых этот человек является их менеджером (атрибут manager содержит DN учетной записи менеджера). Возможно, вам придется настроить его для ваших нужд.

Если вам нужен объект UserPrincipal для результирующих пользователей, вы можете сделать это с помощью этого (где переменная distinguishedName — это DN пользователя):

UserPrincipal.FindByIdentity(context, IdentityType.DistinguishedName, distinguishedName)

Просто имейте в виду, что атрибут manager не является проиндексировано. Так что, если это ваш единственный критерий (помимо (objectClass=user)), то AD нужно просмотреть каждого пользователя, чтобы найти совпадения. Это может или не может быть очень медленным в вашей среде.

Лично я предпочитаю использовать DirectorySearcher и DirectoryEntry напрямую. Я считаю, что все пространство имен System.DirectoryServices.AccountManagement очень медленное. Я написал статью о том, как повысить производительность с помощью пространства имен System.DirectoryServices напрямую: Active Directory: лучшая производительность

person Gabriel Luci    schedule 25.02.2019
comment
На самом деле вы можете расширить класс UserPrincipal, чтобы сделать это (вместе с переопределением методов Find). См. ТАК здесь - person PBMe_HikeIt; 27.04.2020
comment
@PBMe_HikeIt Если хочешь, конечно. Но использование DirectorySearcher/DirectoryEntry всегда в любом случае работает быстрее, чем PrincipalSearcher/UserPrincipal. - person Gabriel Luci; 27.04.2020