Active Directory LDAP Query by sAMAccountName and Domain

Comment faire une requête D'un magasin LDAP par nom et domaine sAMAccountName? Quelle est la propriété "domain" nommée dans Active Directory ou LDAP?

c'est Ce que j'ai pour le filtre jusqu'à présent. J'aimerais pouvoir ajouter dans le domaine:

(&(objectCategory=Person)(sAMAccountName=BTYNDALL))
20
demandé sur GEOCHET 2009-02-03 20:13:51

7 réponses

tout d'abord, modifiez votre filtre de recherche pour ne Rechercher que les utilisateurs et non les contacts:

(&(objectCategory=person)(objectClass=user)(sAMAccountName=BTYNDALL))

vous pouvez énumérer tous les domaines d'une forêt en se connectant à la partition de configuration et en énumérant toutes les entrées dans le conteneur de partitions. Désolé, je n'ai pas de code C# en ce moment mais voici un code vbscript que j'ai utilisé dans le passé:

Set objRootDSE = GetObject("LDAP://RootDSE")
AdComm.Properties("Sort on") = "name"
AdComm.CommandText = "<LDAP://cn=Partitions," & _
    objRootDSE.Get("ConfigurationNamingContext") & ">;" & _
        "(&(objectcategory=crossRef)(systemFlags=3));" & _
            "name,nCName,dnsRoot;onelevel"
set AdRs = AdComm.Execute

à partir de ce que vous pouvez récupérer le nom et le DN-root de chaque partition:

AdRs.MoveFirst
With AdRs
  While Not .EOF
    dnsRoot = .Fields("dnsRoot")

    Set objOption = Document.createElement("OPTION")
    objOption.Text = dnsRoot(0)
    objOption.Value = "LDAP://" & dnsRoot(0) & "/" & .Fields("nCName").Value
    Domain.Add(objOption)
    .MoveNext 
  Wend 
End With
19
répondu Dscoduc 2009-02-04 22:27:00

vous pouvez utiliser les requêtes suivantes""

utilisateurs dont le nom de connexion (pré-Windows 2000) est égal à John

(&(objectCategory=person)(objectClass=user)(!sAMAccountType=805306370)(sAMAccountName=**John**))

Tous Les Utilisateurs

(&(objectCategory=person)(objectClass=user)(!sAMAccountType=805306370))

Utilisateurs Autorisés

(&(objectCategory=person)(objectClass=user)(!sAMAccountType=805306370)(!userAccountControl:1.2.840.113556.1.4.803:=2))

Utilisateurs Handicapés

(&(objectCategory=person)(objectClass=user)(!sAMAccountType=805306370)(userAccountControl:1.2.840.113556.1.4.803:=2))

LockedOut Users

(&(objectCategory=person)(objectClass=user)(!sAMAccountType=805306370)(lockouttime>=1))
12
répondu kombsh 2015-09-15 06:38:52

la meilleure façon de rechercher utilisateurs est (sAMAccountType=805306368) .

ou pour les utilisateurs handicapés:

(&(sAMAccountType=805306368)(userAccountControl:1.2.840.113556.1.4.803:=2))

ou pour les utilisateurs actifs:

(&(sAMAccountType=805306368)(!(userAccountControl:1.2.840.113556.1.4.803:=2)))

je trouve que LDAP n'est pas si léger qu'il aurait dû l'être.

Aussi des ressources pour commun des requêtes LDAP - essayer pour les trouver vous - même et vous serez précieux temps et certainement faire des erreurs.

en ce qui concerne les domaines: cela n'est pas possible dans une seule requête parce que le domaine fait partie de l'utilisateur distinguisedName ( DN ) qui, sur Microsoft AD, n'est pas searchable par correspondance partielle.

8
répondu sorin 2012-04-07 09:43:27

"Domaine" n'est pas une propriété d'un objet LDAP. C'est plus comme le nom de la base de données l'objet est stocké.

vous devez donc vous connecter à la bonne base de données (en termes LDAP: " bind to the domain/directory server " ) pour effectuer une recherche dans cette base de données.

une fois que vous avez relié avec succès, votre requête dans sa forme actuelle est tout ce dont vous avez besoin.

BTW: choisir "ObjectCategory=Person" au-dessus de "ObjectClass=user" était une bonne décision. Dans la ma, le premier est une "propriété indexée" avec d'excellentes performances, ce dernier n'est pas indexé et un peu plus lent.

5
répondu Tomalak 2009-02-03 18:13:53

si vous utilisez .NET, utilisez la classe DirectorySearcher . Vous pouvez passer dans votre domaine comme une chaîne dans le constructeur.

// if you domain is domain.com...
string username = "user"
string domain = "LDAP://DC=domain,DC=com";
DirectorySearcher search = new DirectorySearcher(domain);
search.Filter = "(SAMAccountName=" + username + ")";
3
répondu Aaron Daniels 2009-02-03 17:30:04

j'ai écrit Un C# class incorporant

  • l'algorithme de Dscoduc,
  • l'optimisation de la requête de sorin,
  • un cache pour le mappage du domaine vers le serveur, et
  • méthode de recherche d'un nom de compte dans le format DOMAIN\sAMAccountName.

cependant, il n'est pas conscient du Site.

using System;
using System.Collections.Generic;
using System.DirectoryServices;
using System.Linq;
using System.Text;

public static class ADUserFinder
{
    private static Dictionary<string, string> _dictDomain2LDAPPath;

    private static Dictionary<string, string> DictDomain2LDAPPath
    {
        get
        {
            if (null == _dictDomain2LDAPPath)
            {
                string configContainer;
                using (DirectoryEntry rootDSE = new DirectoryEntry("LDAP://RootDSE"))
                    configContainer = rootDSE.Properties["ConfigurationNamingContext"].Value.ToString();

                using (DirectoryEntry partitionsContainer = new DirectoryEntry("LDAP://CN=Partitions," + configContainer))
                using (DirectorySearcher dsPartitions = new DirectorySearcher(
                        partitionsContainer,
                        "(&(objectcategory=crossRef)(systemFlags=3))",
                        new string[] { "name", "nCName", "dnsRoot" },
                        SearchScope.OneLevel
                    ))
                using (SearchResultCollection srcPartitions = dsPartitions.FindAll())
                {
                    _dictDomain2LDAPPath = srcPartitions.OfType<SearchResult>()
                        .ToDictionary(
                        result => result.Properties["name"][0].ToString(), // the DOMAIN part
                        result => $"LDAP://{result.Properties["dnsRoot"][0]}/{result.Properties["nCName"][0]}"
                    );
                }
            }

            return _dictDomain2LDAPPath;
        }
    }

    private static DirectoryEntry FindRootEntry(string domainPart)
    {
        if (DictDomain2LDAPPath.ContainsKey(domainPart))
            return new DirectoryEntry(DictDomain2LDAPPath[domainPart]);
        else
            throw new ArgumentException($"Domain \"{domainPart}\" is unknown in Active Directory");
    }

    public static DirectoryEntry FindUser(string domain, string sAMAccountName)
    {
        using (DirectoryEntry rootEntryForDomain = FindRootEntry(domain))
        using (DirectorySearcher dsUser = new DirectorySearcher(
                rootEntryForDomain,
                $"(&(sAMAccountType=805306368)(sAMAccountName={EscapeLdapSearchFilter(sAMAccountName)}))" // magic number 805306368 means "user objects", it's more efficient than (objectClass=user)
            ))
            return dsUser.FindOne().GetDirectoryEntry();
    }

    public static DirectoryEntry FindUser(string domainBackslashSAMAccountName)
    {
        string[] domainAndsAMAccountName = domainBackslashSAMAccountName.Split('\');
        if (domainAndsAMAccountName.Length != 2)
            throw new ArgumentException($"User name \"{domainBackslashSAMAccountName}\" is not in correct format DOMAIN\SAMACCOUNTNAME", "DomainBackslashSAMAccountName");

        string domain = domainAndsAMAccountName[0];
        string sAMAccountName = domainAndsAMAccountName[1];

        return FindUser(domain, sAMAccountName);
    }

    /// <summary>
    /// Escapes the LDAP search filter to prevent LDAP injection attacks.
    /// Copied from /q/how-to-escape-a-string-in-c-for-use-in-an-ldap-query-26971/"searchFilter">The search filter.</param>
    /// <see cref="https://blogs.oracle.com/shankar/entry/what_is_ldap_injection" />
    /// <see cref="http://msdn.microsoft.com/en-us/library/aa746475.aspx" />
    /// <returns>The escaped search filter.</returns>
    private static string EscapeLdapSearchFilter(string searchFilter)
    {
        StringBuilder escape = new StringBuilder();
        for (int i = 0; i < searchFilter.Length; ++i)
        {
            char current = searchFilter[i];
            switch (current)
            {
                case '\':
                    escape.Append(@"c");
                    break;
                case '*':
                    escape.Append(@"a");
                    break;
                case '(':
                    escape.Append(@"");
                    break;
                case ')':
                    escape.Append(@"");
                    break;
                case '\u0000':
                    escape.Append(@""151900920"");
                    break;
                case '/':
                    escape.Append(@"f");
                    break;
                default:
                    escape.Append(current);
                    break;
            }
        }

        return escape.ToString();
    }
}
0
répondu Froggy 2018-08-23 13:43:34