2012-03-23 16 views
13

Deseo poder obtener el ID de usuario de un usuario en Active Directory utilizando el nombre para mostrar de ese usuario. El nombre de visualización se obtiene a partir de una base de datos, y ha sido almacenada durante esa sesión de usuario utilizando el código siguiente para obtener el nombre de visualización:¿Cómo obtener un nombre de usuario en Active Directory a partir de un nombre para mostrar en C#?

using System.DirectoryServices.AccountManagement; 

    private string GetDisplayName() 
    { 
     // set up domain context 
     PrincipalContext ctx = new PrincipalContext(ContextType.Domain); 

     // find currently logged in user 
     UserPrincipal user = UserPrincipal.Current; 

     return user.DisplayName; 
    } 

En esta ocasión, me gustaría contar con un método llamado GetUserIdFromDisplayName() que devuelve el Nombre de inicio de sesión de Active Directory. ¿Algunas ideas?

+1

No lo he verificado, así que no estoy 100% seguro, pero creo que quieres la propiedad 'SamAccountName'. – CodingGorilla

+0

¿Crees que esto es posible? Dudo que los nombres para mostrar de los usuarios sean únicos. Posiblemente daría lugar a resultados de múltiples líneas. –

+0

Es cierto. Ahora considero usar GUIDs usando la respuesta a continuación. –

Respuesta

28

Creo que puede hacerlo mucho más fácilmente que con la respuesta de David utilizando la funcionalidad incorporada del espacio de nombres System.DirectoryServices.AccountManagement (S.DS.AM).

Básicamente, se puede definir un contexto de dominio y encontrar fácilmente los usuarios y/o grupos en el año:

using System.DirectoryServices.AccountManagement; 

private string GetUserIdFromDisplayName(string displayName) 
{ 
    // set up domain context 
    using(PrincipalContext ctx = new PrincipalContext(ContextType.Domain)) 
    { 
     // find user by display name 
     UserPrincipal user = UserPrincipal.FindByIdentity(ctx, displayName); 

     // 
     if (user != null) 
     { 
      return user.SamAccountName; 
      // or maybe you need user.UserPrincipalName; 
     } 
     else 
     { 
      return string.Empty; 
     } 
    } 
} 

no veo ninguna necesidad de ir a la DirectoryEntry objeto fundamental, en realidad - a no ser que ninguno de las propiedades del UserPrincipal realmente son lo que estás buscando.

PD: si la búsqueda por nombre de presentación no debe trabajar (no tengo un AD a la mano para probarlo ahora mismo) - siempre se puede también utilizar el PrincipalSearcher para encontrar su usuario:

using System.DirectoryServices.AccountManagement; 

private string GetUserIdFromDisplayName(string displayName) 
{ 
    // set up domain context 
    using(PrincipalContext ctx = new PrincipalContext(ContextType.Domain)) 
    { 
     // define a "query-by-example" principal - here, we search for a UserPrincipal 
     // and with the display name passed in 
     UserPrincipal qbeUser = new UserPrincipal(ctx); 
     qbeUser.DisplayName = displayName; 

     // create your principal searcher passing in the QBE principal  
     PrincipalSearcher srch = new PrincipalSearcher(qbeUser); 

     // find match - if exists 
     UserPrincipal user = srch.FindOne() as UserPrincipal; 

     if (user != null) 
     { 
      return user.SamAccountName; 
      // or maybe you need user.UserPrincipalName; 
     } 
     else 
     { 
      return string.Empty; 
     } 
    } 
} 
+2

+1, más fácil y más rápido, y también encuentra las entradas DOMAIN \ USERID – smirkingman

+0

Pude encontrar usuarios por su DOMINIO \ NOMBRE DE USUARIO con 'UserPrincipal.FindByIdentity (ctx, IdentityTypes.SamAccountName, username)', así que supongo que desea devuelve 'user.SamAccountName' como los estados del código. – Pakman

7

UserPrincipal tiene un método GetUnderlyingObject() que devolverá el DirectoryEntry.

Get DirectoryEntry del Director:

private DirectoryEntry GetDirectoryEntryFromUserPrincipal(Principal user) 
{ 
    return (DirectoryEntry)user.GetUnderlyingObject(); 
} 

Get DirectoryEntry de dominio y el nombre de la cuenta:

private DirectoryEntry GetDirectoryEntryFromDomainAndUsername(string domainName, string userName) 
{ 
    // Get the sid from the NT account name 
    var sid = (SecurityIdentifier) new NTAccount(domainName, accountName) 
        .Translate(typeof(SecurityIdentifier)); 

    // Get the directory entry for the LDAP service account 
    var serviceEntry = new DirectoryEntry("LDAP://{address}", "serviceUsername", "servicePassword"); 

    var mySearcher = new DirectorySearcher(serviceEntry) 
     { 
      Filter = string.Format("(&(ObjectSid={0}))", sid.Value) 
     }; 

    return mySearcher.FindOne().GetDirectoryEntry(); 
} 

vez que tenga el DirectoryEntry utilizar la propiedad Guid para obtener de Object-Guid

la entrada
private Guid GetObjectGuidFromDirectoryEntry(DirectoryEntry entry) 
{ 
    // return the Guid this is the Object-Guid (ignore NativeGuid) 
    return entry.Guid; 
} 

Para rastrear una cuenta de usuario en la aplicación en una cuenta de directorio: utilice siempre el Object-Guid como "Este valor se establece cuando el objeto se crea y no se puede cambiar".
Los nombres de las cuentas NT y SAM pueden cambiar si el usuario cambia de dominio o, más comúnmente, cambia su nombre (matrimonio, cambio de nombre legal, etc.) y no debe utilizarse para rastrear a un usuario.

Para obtener el nombre de la cuenta NT (dominio \ nombre de usuario):

private string GetNTAccountNameFromDirectoryEntry(DirectoryEntry entry) 
{ 
    PropertyValueCollection propertyValueCollection = entry.Properties["objectsid"]; 

    SecurityIdentifier sid = new SecurityIdentifier((byte[]) propertyValueCollection[0], 0); 

    NTAccount ntAccount = (NTAccount)sid.Translate(typeof (NTAccount)); 

    return account.ToString(); 
} 

Para obtener el nombre de la cuenta SAM (nombre de usuario @ dominio):

private string GetSAMAccountFromDirectoryEntry(DirectoryEntry entry) 
{ 
    return entry.Properties["Name"].Value; 
} 

Y aquí está el exhaustive list de todos los atributos de Active Directory. Use el "Ldap-Display-Name" cuando obtenga el valor de Properties
, p. Properties["Ldap-Display-Name"]

Display-Name (FirstName MI LastName) pueden ser útiles.

+0

Gracias! Entonces supongo que debe obtener objetos 'UserPrincipal' de un grupo AD haciendo algo como esto: http://social.msdn.microsoft.com/Forums/en/csharpgeneral/thread/ecb16a63-6619-4c68-a77c-8bb2682fc1be –

+0

Eso funcionaría. Vi que estabas usando 'UserPrincipal.Current' en tu pregunta. Esto funciona si la aplicación web está alojada en el dominio, usa "Seguridad de Windows" o es una aplicación nativa que se ejecuta en una sesión de usuario. Si solo puede consultar AD, obtenga la entrada del directorio directamente filtrando por SAM-Account-Name. – David

+0

Se agregó GetDirectoryEntryFromDomainAndUsername. Esto podría necesitar un poco de ajuste ya que no estoy en un entorno donde pueda probar todo esto contra un servidor AD. – David

Cuestiones relacionadas