2008-10-02 9 views
7

Je suis peut-être simplement stupide, mais j'essaie de trouver un utilisateur dans Active Directory à partir de C#, en utilisant le nom de connexion ("domaine \ utilisateur").Trouver un utilisateur dans Active Directory avec le nom de connexion

Mon « squelette » Recherche AD fonctionnalité ressemble à ceci habituellement:

de = new DirectoryEntry(string.Format("LDAP://{0}", ADSearchBase), null, null, AuthenticationTypes.Secure); 
ds = new DirectorySearcher(de); 
ds.SearchScope = SearchScope.Subtree; 
ds.PropertiesToLoad.Add("directReports"); 
ds.PageSize = 10; 
ds.ServerPageTimeLimit = TimeSpan.FromSeconds(2); 
SearchResult sr = ds.FindOne(); 

Maintenant, cela fonctionne si je le DN complet de l'utilisateur (ADSearchBase pointe généralement aux « Nos utilisateurs » OU dans Active Directory), mais je n'ai simplement aucune idée de la façon de rechercher un utilisateur basé sur la syntaxe "domain \ user".

Des pointeurs?

Répondre

9

Vous devez définir un filtre (DirectorySearcher.Filter) quelque chose comme:

"(& (objectCategory = person) (objectClass = user) (sAMAccountName = {0}))"

Notez que vous spécifiez uniquement le nom d'utilisateur (sans le domaine) pour la propriété sAMAccountName. Pour rechercher un domaine \ utilisateur, localisez d'abord le contexte de dénomination du domaine requis, puis recherchez sAMAccountName. Par ailleurs, lors de la création de chaînes de requête LDAP à l'aide de String.Format, vous devez généralement faire attention à l'échappement des caractères spéciaux. Il n'est probablement pas nécessaire pour un nom de compte, mais peut l'être si vous effectuez une recherche par d'autres propriétés, telles que la première propriété (givenName) ou le dernier nom (propriété sn) de l'utilisateur. J'ai une méthode utilitaire EscapeFilterLiteral pour faire ceci, vous construisez votre chaîne comme ceci:

String.Format("(&(objectCategory=person)(objectClass=user)(sn={0}))", 
       EscapeFilterLiteral(lastName, false)); 

où EscapeFilterLiteral est mis en œuvre comme suit:

public static string EscapeFilterLiteral(string literal, bool escapeWildcards) 
{ 
    if (literal == null) throw new ArgumentNullException("literal"); 

    literal = literal.Replace("\\", "\\5c"); 
    literal = literal.Replace("(", "\\28"); 
    literal = literal.Replace(")", "\\29"); 
    literal = literal.Replace("\0", "\\00"); 
    literal = literal.Replace("/", "\\2f"); 
    if (escapeWildcards) literal = literal.Replace("*", "\\2a"); 
    return literal; 
} 

Cette implémentation vous permet de traiter le caractère * dans le cadre du literal (escapeWildcard = true) ou en tant que caractère générique (escapeWildcard = false). MISE À JOUR: Cela n'a rien à voir avec votre question, mais l'exemple que vous avez posté n'appelle pas Dispose sur les objets jetables qu'il utilise. Comme tous les objets jetables, ces objets (DirectoryEntry, DirectorySearcher, SearchResultCollection) doivent toujours être éliminés, normalement avec l'instruction using. Voir this post pour plus d'informations.

+0

Comment trouvez-vous * d'abord trouver le contexte de nommage pour le domaine requis, recherche alors il *? – Sam

0

Merci. J'ai pensé que je peux obtenir le domaine (au moins dans mon AD) en spécifiant "LDAP: // {0} .somedomain.com/DC = {0}, DC = somedomain, DC = com", en remplaçant {0} par le domaine, qui fonctionne dans notre environnement au moins.

Une question cependant: sAMAccountName semble dépréciée: The logon name used to support clients and servers running older versions of the operating system, such as Windows NT 4.0, Windows 95, Windows 98, and LAN Manager. This attribute must be less than 20 characters to support older clients.

Est-ce toujours la meilleure approche pour elle? Ou y a-t-il un champ plus "moderne" à interroger? (Windows 2003 Active Directory, Windows XP ou 2003 clients, .net 3.0)

Modifier: Merci encore. Notre structure est un peu compliquée: nous avons une grande forêt "domain.com", avec plusieurs domaines pour les bureaux régionaux. Essentiellement: Le Login est "quelque chose \ nom d'utilisateur", le domaine complet nous quelque chose.domaine.com et le courrier est [email protected] (sans le quelque chose), mais le nom principal est [email protected] Je vais manuellement "traduire" quelque chose \ nom d'utilisateur à [email protected], car cela semble être le moyen le plus robuste. D'autant plus que je veux garder la fonction Auto-Discovery.

+0

Je pense qu'un moyen plus moderne consiste à utiliser la propriété userPrincipalName - qui est au format RFC822 (généralement l'adresse e-mail de l'utilisateur). Mais j'utilise toujours sAMAccountName. – Joe

-1

Nom de connexion (pré-Windows 2000)

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

Nom de connexion (Windows 2000 et au-dessus)

"(&(objectCategory=person)(objectClass=user)(!sAMAccountType=805306370)(userPrincipalName=John))" 
+0

Ne fonctionne pas pour Windows 2000 et supérieur – Mikalai

Questions connexes