Directorio activo: obtener grupos donde un usuario es miembro

Me gustaría encontrar la lista de grupos donde un usuario es miembro. Probé varias soluciones desde http://www.codeproject.com/KB/system/everythingInAD.aspx pero no obtuve ningún resultado.

Este código me da un “verdadero”, significa que LDAP se está ejecutando:

public static bool Exists(string objectPath) { bool found = false; if (DirectoryEntry.Exists("LDAP://" + objectPath)) found = true; return found; } 

Gracias,

Actualización 1:

 public ArrayList Groups(string userDn, bool recursive) { ArrayList groupMemberships = new ArrayList(); return AttributeValuesMultiString("memberOf", "LDAP-Server", groupMemberships, recursive); } public ArrayList AttributeValuesMultiString(string attributeName, string objectDn, ArrayList valuesCollection, bool recursive) { DirectoryEntry ent = new DirectoryEntry(objectDn); PropertyValueCollection ValueCollection = ent.Properties[attributeName]; IEnumerator en = ValueCollection.GetEnumerator(); while (en.MoveNext()) { if (en.Current != null) { if (!valuesCollection.Contains(en.Current.ToString())) { valuesCollection.Add(en.Current.ToString()); if (recursive) { AttributeValuesMultiString(attributeName, "LDAP://" + en.Current.ToString(), valuesCollection, true); } } } } ent.Close(); ent.Dispose(); return valuesCollection; } 

Tengo una excepción en:

 PropertyValueCollection ValueCollection = ent.Properties[attributeName]; 

“COMException fue sin manejar”

En .NET 4 puede hacer esto muy fácilmente con la nueva clase UserPrincipal de la siguiente manera:

 using (PrincipalContext context = new PrincipalContext(ContextType.Domain)) { UserPrincipal user = UserPrincipal.FindByIdentity(context, IdentityType.SamAccountName, "your_login"); foreach (var group in user.GetGroups()) { Console.WriteLine(group.Name); } } 

Debe agregar una referencia a System.DirectoryServices.AccountManagement para ingresar los tipos requeridos.

Encontré la solución en stackoverflow. El formato connectionString es así:

 LDAP://domain.subdomain.com:389/DC=domain,DC=subdomain,DC=com 

El código :

  public IList GetGroupsByUser(string ldapConnectionString, string username) { IList groupList = new List(); var identity = WindowsIdentity.GetCurrent().User; var allDomains = Forest.GetCurrentForest().Domains.Cast(); var allSearcher = allDomains.Select(domain => { var searcher = new DirectorySearcher(new DirectoryEntry(ldapConnectionString)); // Apply some filter to focus on only some specfic objects searcher.Filter = String.Format("(&(&(objectCategory=person)(objectClass=user)(name=*{0}*)))", username); return searcher; }); var directoryEntriesFound = allSearcher .SelectMany(searcher => searcher.FindAll() .Cast() .Select(result => result.GetDirectoryEntry())); var memberOf = directoryEntriesFound.Select(entry => { using (entry) { return new { Name = entry.Name, GroupName = ((object[])entry.Properties["MemberOf"].Value).Select(obj => obj.ToString()) }; } }); foreach (var item in memberOf) foreach (var groupName in item.GroupName) groupList.Add(groupName); return groupList; } 

¿Estás seguro de que el script anterior es correcto y funciona correctamente? No creo que tenga en cuenta las membresías de grupos nesteds, por lo que me temo que es posible que no esté obteniendo el conjunto completo de todos los grupos a los que pertenece un usuario.

Verá, un usuario podría ser un miembro del Grupo X, y el Grupo X podría a su vez ser un miembro del Grupo Y, por lo tanto, el usuario también sería un miembro del Grupo Y.

Creo que la secuencia de comandos mencionada anteriormente puede no ser capaz de expandir y enumerar las pertenencias a grupos nesteds.

También sugeriría considerar este ángulo, si está interesado en obtener el conjunto completo de membresías a las que pertenece el usuario.

Creo que también hay otros problemas relacionados con la determinación de la pertenencia a un grupo. Hay una buena discusión aquí si está interesado en aprender más:

http://www.activedirsec.org/t39703252/why-is-it-so-hard-to-enumerate-nested-group-memberships-in-a/

Lo deseo mucho más fácil, pero no parece ser así 🙁

Usa este código en lugar de tu versión. Esto te dará la lista. La diferencia entre este y el original es el uso de DirectorySearcher.

  public ArrayList AttributeValuesMultiString(string attributeName, string objectDn, ArrayList valuesCollection, bool recursive) { using (DirectoryEntry ent = new DirectoryEntry(objectDn)) { using (DirectorySearcher searcher = new DirectorySearcher(ent)) { searcher.PropertiesToLoad.Add(attributeName); var result = searcher.FindOne(); ResultPropertyValueCollection ValueCollection = result.Properties[attributeName]; IEnumerator en = ValueCollection.GetEnumerator(); while (en.MoveNext()) { if (en.Current != null) { if (!valuesCollection.Contains(en.Current.ToString())) { valuesCollection.Add(en.Current.ToString()); if (recursive) { AttributeValuesMultiString(attributeName, "LDAP://" + en.Current.ToString(), valuesCollection, true); } } } } } } return valuesCollection; }