web-dev-qa-db-fra.com

Un moyen rapide de récupérer les informations utilisateur Active Directory

Comment interroger les informations utilisateur de Active Directory ? J'ai du code qui fonctionne, mais c'est vraiment lent. J'utilise C #. Voici le code que j'utilise actuellement:

    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();
    }

À quoi ressemblerait un code plus rapide pour obtenir des informations utilisateur d'AD?

24
Adyt

La raison pour laquelle votre code est lent est que votre requête LDAP récupère chaque objet utilisateur unique de votre domaine même si vous n'êtes intéressé que par un seul utilisateur avec un nom de "Adit":

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

Donc, pour optimiser, vous devez restreindre votre requête LDAP à l'utilisateur qui vous intéresse. Essayez quelque chose comme:

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

De plus, n'oubliez pas de disposer ces objets une fois terminé:

  • DirectoryEntry dEntry
  • DirectorySearcher dSearcher
17
barneytron

Tu peux appeler UserPrincipal.FindByIdentity à l'intérieur System.DirectoryServices.AccountManagement:

using System.DirectoryServices.AccountManagement;

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

Eh bien, si vous savez où réside votre utilisateur dans la hiérarchie AD (par exemple, très probablement dans le conteneur "Utilisateurs", s'il s'agit d'un petit réseau), vous pouvez également vous lier directement au compte d'utilisateur, au lieu de le rechercher.

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

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

Et si vous êtes déjà sur .NET 3.5, vous pouvez même utiliser l'espace de noms System.DirectorySrevices.AccountManagement largement étendu avec des classes fortement typées pour chacun des objets AD les plus courants:

// 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");

Il y a beaucoup d'informations sur System.DirectoryServices.AccountManagement - consultez cet excellent article sur MSDN par Joe Kaplan et Ethan Wilansky sur le sujet.

13
marc_s

Vous pouvez simplifier ce code pour:

        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
        }

Si vous pouvez préciser où se trouve l'utilisateur, vous pouvez définir searcher.SearchRoot sur une unité d'organisation spécifique sous laquelle l'utilisateur se trouve.

Vous devez également utiliser objectCategory au lieu de objectClass car objectCategory est indexé par défaut.

Vous devriez également envisager de rechercher un attribut autre que CN. Par exemple, il peut être plus judicieux de rechercher le nom d'utilisateur (sAMAccountName) car il est garanti d'être unique.

7
Steve Evans

Je ne sais pas combien de votre "lenteur" sera due à la boucle que vous faites pour trouver des entrées avec des valeurs d'attribut particulières, mais vous pouvez supprimer cette boucle en étant plus spécifique avec votre filtre. Essayez cette page pour quelques conseils ... Syntaxe du filtre de recherche

1
Handleman