Listar los grupos de un usuario de Active Directory en C#

1:06 pm Proyectos

Queremos hacer una aplicación para windows (o para la Web) en .NET donde debemos comprobar si un usuario pertenece o no a unos grupos determinados del dominio.  Esto nos sirve para saber si el usuario puede entrar en la aplicación y qué permisos tiene. Lo normal es que un grupo contenga a un usuario directamente, pero, ¿que sucede si un usuario no pertenece directamente a un grupo A, sino que pertenece a un grupo B que a su vez pertenece al grupo A?.

Para que funcione en todos los casos se debe buscar el aributo tokenGroups de la cuenta del usuario en el Directorio Activo. Este atributo contiene todos los SIDs de los grupos a los que pertenece el usuario directa o indirectamente.

Aquí pongo un ejemplo comentando de cómo se puede hacer:

// Creamos un objeto DirectoryEntry para conectarnos al directorio activo
DirectoryEntry adsRoot = new DirectoryEntry("LDAP://" + Environment.GetEnvironmentVariable("USERDOMAIN"));
// Creamos un objeto DirectorySearcher para hacer una búsqueda en el directorio activo
DirectorySearcher adsSearch = new DirectorySearcher(adsRoot);
 
try
{
    // Ponemos como filtro que busque el usuario actual
    adsSearch.Filter = "samAccountName=" + Environment.GetEnvironmentVariable("USERNAME");
 
    // Extraemos la primera coincidencia
    SearchResult oResult;
    oResult = adsSearch.FindOne();
 
    // Obtenemos el objeto de ese usuario
    DirectoryEntry usuario = oResult.GetDirectoryEntry();
 
    // Obtenemos la lista de SID de los grupos a los que pertenece
    usuario.RefreshCache(new string[] { "tokenGroups" });
 
    // Creamos una variable StringBuilder donde ir añadiendo los SID para crear un filtro de búsqueda
    StringBuilder sids = new StringBuilder();
    sids.Append("(|");
    foreach (byte[] sid in usuario.Properties["tokenGroups"])
    {
        sids.Append("(objectSid=");
        for (int indice = 0; indice < sid.Length; indice++)
        {
            sids.AppendFormat("\\{0}", sid[indice].ToString("X2"));
        }
        sids.AppendFormat(")");
    }
    sids.Append(")");
 
    // Creamos un objeto DirectorySearcher con el filtro antes generado y buscamos todas la coincidencias
    DirectorySearcher ds = new DirectorySearcher(adsRoot, sids.ToString());
    SearchResultCollection src = ds.FindAll();
 
    // Recorremos toda la lista de grupos devueltos
    foreach (SearchResult sr in src)
    {
        String sGrupo = (String) sr.Properties["samAccountName"][0];
        // A partir de aquí hacer lo que corresponda con cada grupo
        ...
    }
}
catch(Exception ex)
{
    Console.WriteLine(ex.Message);
}
Leave a comment

Your comment

You can use these tags: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong> <pre lang="" line="" escaped="" highlight="">

Please note: Comment moderation is enabled and may delay your comment. There is no need to resubmit your comment.