namespace - directorysearcher c#
Cómo determinar todos los grupos a los que pertenece un usuario(incluidos los grupos anidados) en ActiveDirectory y.NET 3.5 (4)
Solución # 1
Este error se informa aquí en Microsoft Connect junto con el siguiente código que soluciona este problema mediante la iteración manual a través de los objetos devueltos PrincipalSearchResult<Principal>
, captura esta excepción y continúa:
PrincipalSearchResult<Principal> groups = user.GetAuthorizationGroups();
var iterGroup = groups.GetEnumerator();
using (iterGroup)
{
while (iterGroup.MoveNext())
{
try
{
Principal p = iterGroup.Current;
Console.WriteLine(p.Name);
}
catch (NoMatchingPrincipalException pex)
{
continue;
}
}
}
Solución # 2
Otra solución alternativa encontrada aquí evita la clase AccountManagement
y usa la API System.DirectoryServices
lugar:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.DirectoryServices;
namespace GetGroupsForADUser
{
class Program
{
static void Main(string[] args)
{
String username = "Gabriel";
List<string> userNestedMembership = new List<string>();
DirectoryEntry domainConnection = new DirectoryEntry(); // Use this to query the default domain
//DirectoryEntry domainConnection = new DirectoryEntry("LDAP://example.com", "username", "password"); // Use this to query a remote domain
DirectorySearcher samSearcher = new DirectorySearcher();
samSearcher.SearchRoot = domainConnection;
samSearcher.Filter = "(samAccountName=" + username + ")";
samSearcher.PropertiesToLoad.Add("displayName");
SearchResult samResult = samSearcher.FindOne();
if (samResult != null)
{
DirectoryEntry theUser = samResult.GetDirectoryEntry();
theUser.RefreshCache(new string[] { "tokenGroups" });
foreach (byte[] resultBytes in theUser.Properties["tokenGroups"])
{
System.Security.Principal.SecurityIdentifier mySID = new System.Security.Principal.SecurityIdentifier(resultBytes, 0);
DirectorySearcher sidSearcher = new DirectorySearcher();
sidSearcher.SearchRoot = domainConnection;
sidSearcher.Filter = "(objectSid=" + mySID.Value + ")";
sidSearcher.PropertiesToLoad.Add("distinguishedName");
SearchResult sidResult = sidSearcher.FindOne();
if (sidResult != null)
{
userNestedMembership.Add((string)sidResult.Properties["distinguishedName"][0]);
}
}
foreach (string myEntry in userNestedMembership)
{
Console.WriteLine(myEntry);
}
}
else
{
Console.WriteLine("The user doesn''t exist");
}
Console.ReadKey();
}
}
}
Tengo una aplicación que utiliza la autorización de ActiveDirecotry y se decidió que necesita admitir grupos de AD anidados, por ejemplo:
MAIN_AD_GROUP
|
|-> SUB_GROUP
|
|-> User
Por lo tanto, el usuario no es directamente miembro de MAIN_AD_GROUP
. Me gustaría poder buscar al usuario de forma recursiva, buscando los grupos anidados en MAIN_AD_GROUP
.
El principal problema es que estoy usando .NET 3.5 y hay un error en System.DirectoryServices.AccountManagement
en .NET 3.5, por lo que el método UserPrincipal.IsMemberOf()
no funcionará para grupos con más de 1500 usuarios . Así que no puedo usar UserPrincipal.IsMemberOf()
y no, tampoco puedo cambiar a .NET 4.
He resuelto este último problema con la siguiente función:
private bool IsMember(Principal userPrincipal, Principal groupPrincipal)
{
using (var groups = userPrincipal.GetGroups())
{
var isMember = groups.Any(g =>
g.DistinguishedName == groupPrincipal.DistinguishedName);
return isMember;
}
}
Pero userPrincipal.GetGroups()
solo devuelve los grupos de los cuales el usuario es miembro directo.
¿Cómo puedo conseguir que esto funcione con grupos anidados?
La forma eficiente es hacer una sola consulta de AD al tener el filtro de DirectorySearcher correcto para, por ejemplo
public bool CheckMemberShip(string userName)
{
bool membership = false;
string connection = "LDAP://"+YOURDOMAIN;
DirectoryEntry entry = new DirectoryEntry(connection);
DirectorySearcher mySearcher = new DirectorySearcher(entry);
mySearcher.Filter = "(&(objectClass=user)(memberOf:1.2.840.113556.1.4.1941:=cn=GROUPNAME,OU=Groups,OU=ABC,OU=ABC,OU=IND,DC=ad,DC=COMPANY,DC=com)(|(sAMAccountName=" + userName + ")))";
SearchResult result = mySearcher.FindOne();
// No search result, hence no membership
if (result == null)
{
membership = false;
}
entry.Close();
entry.Dispose();
mySearcher.Dispose();
membership = true;
return membership;
}
Debe reemplazar YOURDOMAIN y GROUPNAME con los valores correctos de su AD.
Es necesario incluir el using System.DirectoryServices;
Sé que este es un tema antiguo, pero es el principal resultado en Google, por lo que en caso de que esto ayude a alguien, esto es lo que se me ocurrió con el uso de AccountManagement, pero facilita mucho esta consulta en particular.
public static class AccountManagementExtensions
{
public static bool IsNestedMemberOf(this Principal principal, GroupPrincipal group)
{
// LDAP Query for memberOf Nested
var filter = String.Format("(&(sAMAccountName={0})(memberOf:1.2.840.113556.1.4.1941:={1}))",
principal.SamAccountName,
group.DistinguishedName
);
var searcher = new DirectorySearcher(filter);
var result = searcher.FindOne();
return result != null;
}
}
Use UserPrincipal.GetAuthorizationGroups()
en su lugar - desde sus documentos de MSDN :
Este método busca todos los grupos de forma recursiva y devuelve los grupos en los que el usuario es miembro. El conjunto devuelto también puede incluir grupos adicionales de los que el sistema consideraría al usuario miembro para fines de autorización.
Los grupos que son devueltos por este método pueden incluir grupos de un alcance y tienda diferentes a los del principal. Por ejemplo, si el principal es un objeto AD DS que tiene un DN de "CN = SpecialGroups, DC = Fabrikam, DC = com, el conjunto devuelto puede contener grupos que pertenecen a" CN = NormalGroups, DC = Fabrikam, DC = com.