2008-10-02 19 views
7

Posiblemente soy estúpido, pero estoy tratando de encontrar un usuario en Active Directory desde C#, usando el nombre de usuario ("dominio \ usuario").Encontrar un usuario en Active Directory con el nombre de usuario

Mi "esqueleto" AD funcionalidad de búsqueda se parece a esto por lo general:

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

Ahora, que funciona si tengo el DN completo del usuario (ADSearchBase por lo general apunta a las "Nuestros usuarios" unidad organizativa en Active Directory), pero simplemente no tengo idea de cómo buscar un usuario en función de la sintaxis "dominio \ usuario".

Cualquier punteros?

Respuesta

9

Es necesario configurar un filtro (DirectorySearcher.Filter) algo como:

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

Tenga en cuenta que solo especifica el nombre de usuario (sin el dominio) para la propiedad sAMAccountName. Para buscar dominio \ usuario, primero busque el contexto de denominación para el dominio requerido, luego busque allí sAMAccountName.

Por cierto, al compilar cadenas de consulta LDAP utilizando String.Format, generalmente debe tener cuidado de evitar caracteres especiales. Probablemente no sea necesario para un nombre de cuenta, pero podría serlo si está buscando otras propiedades, como el primer nombre del usuario (propiedad givenName) o el apellido (propiedad sn). Tengo un método de utilidad EscapeFilterLiteral para hacer esto: se construye la cadena de la siguiente manera:

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

donde EscapeFilterLiteral se implementa de la siguiente manera:

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

Esta aplicación le permite tratar el carácter * como parte de la literal (escapeWildcard = true) o como un carácter comodín (escapeWildcard = false).

ACTUALIZACIÓN: Esto no tiene nada que ver con su pregunta, pero el ejemplo que publicó no llama a Dispose sobre los objetos desechables que utiliza. Al igual que todos los objetos desechables, estos objetos (DirectoryEntry, DirectorySearcher, SearchResultCollection) siempre deben desecharse, normalmente con la instrucción using. Vea this post para más información.

+0

¿Cómo * primero localizar el contexto de nomenclatura para el dominio deseado, a continuación, buscar allí *? – Sam

0

Gracias. Pensé que podía obtener el dominio (al menos en mi AD) especificando "LDAP: // {0} .somedomain.com/DC = {0}, DC = somedomain, DC = com", reemplazando {0} con el dominio, que funciona en nuestro entorno, al menos.

Una pregunta, sin embargo: sAMAccountName parece deprecia: 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.

¿Sigue siendo el mejor enfoque a ella? ¿O hay un campo más "moderno" para consultar? (Windows 2003 Active Directory, Windows XP o 2003 Clientes, .net 3.0)

Edit: Gracias de nuevo. Nuestra estructura es un poco complicada: tenemos un gran bosque "domain.com", con varios dominios para oficinas regionales. Esencialmente: el inicio de sesión es "algo \ nombre de usuario", el dominio completo es algo.dominio.com y el correo es [email protected] (sin el algo), pero el nombre principal es [email protected] Voy a "traducir" manualmente algo \ username a [email protected], ya que esta parece ser la forma más robusta. Especialmente porque quiero mantener la característica Auto-Discovery.

+0

Creo que una forma más moderna es usar la propiedad userPrincipalName, que está en formato RFC822 (generalmente la dirección de correo electrónico del usuario). Pero siempre uso sAMAccountName. – Joe

-1

Nombre de conexión (anterior a Windows 2000)

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

Nombre de conexión (Windows 2000 y superior)

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

No funciona para Windows 2000 y superior – Mikalai

Cuestiones relacionadas