Подтвердить что ты не робот

Быстрый способ получить информацию о пользователе Active Directory

Как запрашивать информацию пользователя из Active Directory? У меня есть код, который работает, но он очень медленный. Я использую С#. Это код, который я использую в настоящее время:

    static void Main(string[] args)
    {
        SearchResultCollection sResults = null;

        try
        {
            //modify this line to include your domain name
            string path = "LDAP://EXTECH";
            //init a directory entry
            DirectoryEntry dEntry = new DirectoryEntry(path);

            //init a directory searcher
            DirectorySearcher dSearcher = new DirectorySearcher(dEntry);

            //This line applies a filter to the search specifying a username to search for
            //modify this line to specify a user name. if you want to search for all
            //users who start with k - set SearchString to "k"
            dSearcher.Filter = "(&(objectClass=user))";

            //perform search on active directory
            sResults = dSearcher.FindAll();

            //loop through results of search
            foreach (SearchResult searchResult in sResults)
            {
                if (searchResult.Properties["CN"][0].ToString() == "Adit")
                {
                    ////loop through the ad properties
                    //foreach (string propertyKey in
                    //searchResult.Properties["st"])
                    //{

                        //pull the collection of objects with this key name
                        ResultPropertyValueCollection valueCollection =
                        searchResult.Properties["manager"];

                        foreach (Object propertyValue in valueCollection)
                        {

                            //loop through the values that have a specific name
                            //an example of a property that would have multiple
                            //collections for the same name would be memberof
                            //Console.WriteLine("Property Name: " + valueCollection..ToString());
                            Console.WriteLine("Property Value: " + (string)propertyValue.ToString());

                            //["sAMAccountName"][0].ToString();
                        }
                    //}
                    Console.WriteLine(" ");
                }
            }
        }
        catch (InvalidOperationException iOe)
        {
            //
        }
        catch (NotSupportedException nSe)
        {
            //
        }
        finally
        {

            // dispose of objects used
            if (sResults != null)
                sResults.Dispose();

        }
        Console.ReadLine();
    }

Как бы быстрее выглядел код для получения информации о пользователе из AD?

4b9b3361

Ответ 1

Причина, по которой ваш код работает медленно, заключается в том, что ваш запрос LDAP извлекает каждый отдельный объект пользователя в вашем домене, даже если вас интересует только один пользователь с общим именем "Adit":

dSearcher.Filter = "(&(objectClass=user))";

Поэтому для оптимизации вам нужно сузить свой запрос LDAP только до интересующего вас пользователя. Попробуйте что-то вроде:

dSearcher.Filter = "(&(objectClass=user)(cn=Adit))";

Кроме того, не забудьте утилизировать эти объекты, когда закончите:

  • DirectoryEntry dEntry
  • DirectorySearcher dSearcher

Ответ 2

Вы можете вызвать UserPrincipal.FindByIdentity внутри System.DirectoryServices.AccountManagement:

using System.DirectoryServices.AccountManagement;

using (var pc = new PrincipalContext(ContextType.Domain, "MyDomainName"))
{
    var user = UserPrincipal.FindByIdentity(pc, IdentityType.SamAccountName, "MyDomainName\\" + userName);
}

Ответ 3

Хорошо, если вы знаете, где ваш пользователь живет в иерархии AD (например, вполне возможно, в контейнере "Пользователи", если это небольшая сеть), вы также можете напрямую привязываться к учетной записи пользователя, а не искать ее.

DirectoryEntry deUser = new DirectoryEntry("LDAP://cn=John Doe,cn=Users,dc=yourdomain,dc=com");

if (deUser != null)
{
  ... do something with your user
}

И если вы уже на .NET 3.5, вы даже можете использовать значительно расширенное пространство имен System.DirectorySrevices.AccountManagement с строго типизированными классами для каждого из наиболее распространенных объектов AD:

// bind to your domain
PrincipalContext pc = new PrincipalContext(ContextType.Domain, "LDAP://dc=yourdomain,dc=com");

// find the user by identity (or many other ways)
UserPrincipal user = UserPrincipal.FindByIdentity(pc, "cn=John Doe");

Здесь много информации о System.DirectoryServices.AccountManagement - ознакомьтесь с этой замечательной статьей на MSDN Джо Капланом и Этаном Вилански на тема.

Ответ 4

Вы можете упростить этот код:

        DirectorySearcher searcher = new DirectorySearcher();
        searcher.Filter = "(&(objectCategory=user)(cn=steve.evans))";

        SearchResultCollection results = searcher.FindAll();

        if (results.Count == 1)
        {
            //do what you want to do
        }
        else if (results.Count == 0)
        {
            //user does not exist
        }
        else
        {
            //found more than one user
            //something is wrong
        }

Если вы можете сузить, где пользователь, вы можете установить поисковик .SearchRoot для конкретного подразделения, которое вы знаете, пользователя.

Вы также должны использовать objectCategory вместо objectClass, поскольку objectCategory индексируется по умолчанию.

Вы также должны рассмотреть поиск по атрибуту, отличному от CN. Например, имеет смысл искать в имени пользователя (sAMAccountName), поскольку он гарантированно уникален.

Ответ 5

Я не уверен, сколько из вашей "медленности" будет связано с циклом, который вы делаете, чтобы найти записи с определенными значениями атрибутов, но вы можете удалить этот цикл, уточнив свой фильтр. Попробуйте эту страницу для некоторых рекомендаций... Синтаксис фильтра поиска