c# authentication - Obtenir tous les rapports directs à partir d'Active Directory





directoryentry example (2)


Tout d'abord, définir Scope sur "subtree" est inutile lorsque vous avez déjà le DN que vous recherchez.

Aussi, que diriez-vous de trouver tous les objets dont la propriété "manager" est la personne que vous recherchez, puis de les parcourir. Cela devrait généralement être plus rapide que l'inverse.

(&(objectCategory=user)(manager=<user-dn-here>))

EDIT: Ce qui suit est important mais n'a été mentionné que dans les commentaires de cette réponse:

Lorsque la chaîne de filtrage est construite comme indiqué ci-dessus, il y a un risque de la casser avec des caractères qui sont valides pour un DN, mais qui ont une signification spéciale dans un filtre. Ceux-ci doivent être échappés :

*   as  \2a
(   as  \28
)   as  \29
\   as  \5c
NUL as  \00
/   as  \2f

// Arbitrary binary data can be represented using the same scheme.

EDIT: Définir le SearchRoot au DN d'un objet, et le SearchScope à la Base est également un moyen rapide de tirer un seul objet sur AD.

J'essaie d'obtenir tous les rapports directs d'un utilisateur via Active Directory, de manière récursive. Donc, compte tenu d'un utilisateur, je finirai avec une liste de tous les utilisateurs qui ont cette personne en tant que gestionnaire ou qui ont une personne en tant que gestionnaire qui a une personne en tant que gestionnaire ... qui a finalement l'utilisateur d'entrée en tant que gestionnaire.

Ma tentative actuelle est plutôt lente:

private static Collection<string> GetDirectReportsInternal(string userDN, out long elapsedTime)
{
    Collection<string> result = new Collection<string>();
    Collection<string> reports = new Collection<string>();

    Stopwatch sw = new Stopwatch();
    sw.Start();

    long allSubElapsed = 0;
    string principalname = string.Empty;

    using (DirectoryEntry directoryEntry = new DirectoryEntry(string.Format("LDAP://{0}",userDN)))
    {
        using (DirectorySearcher ds = new DirectorySearcher(directoryEntry))
        {
            ds.SearchScope = SearchScope.Subtree;
            ds.PropertiesToLoad.Clear();
            ds.PropertiesToLoad.Add("directReports");
            ds.PropertiesToLoad.Add("userPrincipalName");
            ds.PageSize = 10;
            ds.ServerPageTimeLimit = TimeSpan.FromSeconds(2);
            SearchResult sr = ds.FindOne();
            if (sr != null)
            {
                principalname = (string)sr.Properties["userPrincipalName"][0];
                foreach (string s in sr.Properties["directReports"])
                {
                    reports.Add(s);
                }
            }
        }
    }

    if (!string.IsNullOrEmpty(principalname))
    {
        result.Add(principalname);
    }

    foreach (string s in reports)
    {
        long subElapsed = 0;
        Collection<string> subResult = GetDirectReportsInternal(s, out subElapsed);
        allSubElapsed += subElapsed;

        foreach (string s2 in subResult)
        {
        result.Add(s2);
        }
    }



    sw.Stop();
    elapsedTime = sw.ElapsedMilliseconds + allSubElapsed;
    return result;
}

Essentiellement, cette fonction prend un nom distinctif en entrée (CN = Michael Stum, OU = test, DC = sub, DC = domaine, DC = com), et avec cela, l'appel à ds.FindOne () est lent.

J'ai trouvé que c'est beaucoup plus rapide de chercher le userPrincipalName. Mon problème: sr.Properties ["directReports"] est juste une liste de chaînes, et c'est le distinguishedName, qui semble lent à chercher.

Je me demande, y at-il un moyen rapide de convertir entre distinguishedName et userPrincipalName? Ou y a-t-il un moyen plus rapide de rechercher un utilisateur si je n'ai que le distinguishedName avec lequel travailler?

Edit: Merci à la réponse! La recherche dans Manager-Field a amélioré la fonction de 90 secondes à 4 secondes. Voici le code nouveau et amélioré, qui est plus rapide et plus lisible (notez qu'il y a probablement un bogue dans la fonctionnalité elapsedTime, mais le noyau de la fonction fonctionne):

private static Collection<string> GetDirectReportsInternal(string ldapBase, string userDN, out long elapsedTime)
{
    Collection<string> result = new Collection<string>();

    Stopwatch sw = new Stopwatch();
    sw.Start();
    string principalname = string.Empty;

    using (DirectoryEntry directoryEntry = new DirectoryEntry(ldapBase))
    {
        using (DirectorySearcher ds = new DirectorySearcher(directoryEntry))
        {
            ds.SearchScope = SearchScope.Subtree;
            ds.PropertiesToLoad.Clear();
            ds.PropertiesToLoad.Add("userPrincipalName");
            ds.PropertiesToLoad.Add("distinguishedName");
            ds.PageSize = 10;
            ds.ServerPageTimeLimit = TimeSpan.FromSeconds(2);
            ds.Filter = string.Format("(&(objectCategory=user)(manager={0}))",userDN);

            using (SearchResultCollection src = ds.FindAll())
            {
                Collection<string> tmp = null;
                long subElapsed = 0;
                foreach (SearchResult sr in src)
                {
                    result.Add((string)sr.Properties["userPrincipalName"][0]);
                    tmp = GetDirectReportsInternal(ldapBase, (string)sr.Properties["distinguishedName"][0], out subElapsed);
                    foreach (string s in tmp)
                    {
                    result.Add(s);
                    }
                }
            }
          }
        }
    sw.Stop();
    elapsedTime = sw.ElapsedMilliseconds;
    return result;
}



Je viens de créer une bibliothèque .NET SFTP . L'une des choses que j'ai apprises au cours du processus est la différence entre FTP et SFTP. Vous communiquez actuellement avec un serveur SSH au lieu d'un serveur FTP. Ce n'est pas seulement le protocole, les commandes sont totalement différentes que vous envoyez au serveur SSH.

Voici un lien vers ma bibliothèque.







c# active-directory ldap