Enumeración de grupos de usuarios anidados usando C#
.net active-directory (1)
He escrito un código que obtiene todos los usuarios de grupos y grupos anidados. También quería asegurarme de que el bucle no ocurriera si la pertenencia al grupo causaba un bucle al tener al primer grupo como miembro del último grupo.
El código que escribí funciona bien pero es un poco lento.
Esta es la primera vez que intento hacer búsquedas AD.
¿Podría alguien echar un vistazo y decirme si el código se ve bien o mal codificado (o peor), o lo he hecho de la manera incorrecta?
using System;
using System.Collections.Generic;
using System.Text;
using System.DirectoryServices;
using System.IO;
namespace Tester3
{
class Program3
{
public static List<string> appGroupList = new List<string>();
public static List<string> userList = new List<string>();
public static List<string> groupList = new List<string>();
public static List<string> groupChecked = new List<string>();
static void Main(string[] args)
{
// Create Output File
StreamWriter outputfile = new StreamWriter("output.txt", false);
appGroupList.Add("GLB-SBCCitrixHelpdesk-DL");
appGroupList.Add("SBC_UKBSAVIA001_PROD_ROL_Siebel");
foreach (string appGroup in appGroupList)
{
string appGroupCN = GetCN(appGroup);
GetMembers(appGroupCN);
groupChecked.Clear();
}
foreach (string item in userList)
{
Console.WriteLine(item);
outputfile.WriteLine(item);
}
outputfile.Flush();
outputfile.Close();
Console.ReadLine();
}
private static string GetCN(string group)
{
string groupCN = string.Empty;
try
{
using (DirectorySearcher search = new DirectorySearcher())
{
search.Filter = "(&(cn=" + group + ")(objectClass=group))";
search.PropertiesToLoad.Add("CN");
SearchResult result = search.FindOne();
if (result != null)
{
groupCN = result.Properties["adsPath"][0].ToString();
groupCN = groupCN.Replace("LDAP://", "");
}
return groupCN;
}
}
catch (Exception)
{
return groupCN;
}
}
public static void GetMembers(string group) // get members using the groups full cn
{
// Check if group has already been checked
if (groupChecked.Contains(group))
{
return;
}
// Add group to groupChecked list
groupChecked.Add(group);
try
{
// Connect to group object
using (DirectoryEntry groupObject = new DirectoryEntry("LDAP://" + group))
{
// Get member of group object
PropertyValueCollection col = groupObject.Properties["member"] as PropertyValueCollection;
// Loop through each member
foreach (object member in col)
{
// Connect to member object
using (DirectoryEntry memberObject = new DirectoryEntry("LDAP://" + member))
{
// Get class of member object
string memberClass = memberObject.Properties["objectClass"][1].ToString();
string memberCN = memberObject.Properties["Name"][0].ToString();
if (!groupChecked.Contains(member.ToString()))
{
if (memberClass.ToLower() == "group")
{
GetMembers(member.ToString());
}
else
{
userList.Add(memberCN);
}
}
else
{
if (memberClass.ToLower() != "group")
{
userList.Add(memberCN);
}
}
}
}
}
}
catch (Exception)
{
}
}
}
}
Si tiene .NET 3.5 y superior, debe consultar el espacio de nombres System.DirectoryServices.AccountManagement
(S.DS.AM). Lea todo al respecto aquí:
- Administración de los principales de seguridad de directorios en .NET Framework 3.5
- Documentos de MSDN en System.DirectoryServices.AccountManagement
Básicamente, puede definir un contexto de dominio y encontrar fácilmente usuarios y / o grupos en AD:
// set up domain context
PrincipalContext ctx = new PrincipalContext(ContextType.Domain);
// find a user
UserPrincipal user = UserPrincipal.FindByIdentity(ctx, "SomeUserName");
if(user != null)
{
// get a user''s group memberships
foreach(Principal principal in me.GetGroups())
{
GroupPrincipal gp = (principal as GroupPrincipal);
if(gp != null)
{
// do something with the group
}
}
}
El nuevo S.DS.AM hace que sea realmente fácil jugar con usuarios y grupos en AD. La llamada a .GetGroups()
también maneja todos los problemas de membresías grupales anidadas, etc., para usted, ¡sin necesidad de lidiar con esa molestia más!