Pour obtenir tous les groupes d'ANNONCES pour un utilisateur particulier?

j'ai coché ce poteau déjà. Mais cela ne répond pas à ma question. Je veux obtenir tous les groupes active directory dans laquelle un utilisateur est membre.

j'ai écrit le code suivant. Mais je ne peux pas aller plus loin car je ne sais pas comment donner le filtre et comment accéder aux propriétés.

class Program
{
    static void Main(string[] args)
    {
        DirectoryEntry de = new DirectoryEntry("LDAP://mydomain.com");
        DirectorySearcher searcher = new DirectorySearcher(de);
        searcher.Filter = "(&(ObjectClass=group))";
        searcher.PropertiesToLoad.Add("distinguishedName");
        searcher.PropertiesToLoad.Add("sAMAccountName");
        searcher.PropertiesToLoad.Add("name");
        searcher.PropertiesToLoad.Add("objectSid");
        SearchResultCollection results = searcher.FindAll();
        int i = 1;
        foreach (SearchResult res in results)
        {
            Console.WriteLine("Result" + Convert.ToString(i++));
            DisplayProperties("distinguishedName", res);
            DisplayProperties("sAMAccouontName", res);
            DisplayProperties("name", res);
            DisplayProperties("objectSid", res);
            Console.WriteLine();
        }

        Console.ReadKey();
    }

    private static void DisplayProperties(string property, SearchResult res)
    {
        Console.WriteLine("t" + property);
        ResultPropertyValueCollection col = res.Properties[property];
        foreach (object o in col)
        {
            Console.WriteLine("tt" + o.ToString());
        }
    }
}

des idées?

30
demandé sur Community 2010-12-16 15:03:28

8 réponses

il suffit d'interroger la propriété "memberOf" et d'itérer à travers le retour, exemple:

            search.PropertiesToLoad.Add("memberOf");
            StringBuilder groupNames = new StringBuilder(); //stuff them in | delimited

                SearchResult result = search.FindOne();
                int propertyCount = result.Properties["memberOf"].Count;
                String dn;
                int equalsIndex, commaIndex;

                for (int propertyCounter = 0; propertyCounter < propertyCount;
                    propertyCounter++)
                {
                    dn = (String)result.Properties["memberOf"][propertyCounter];

                    equalsIndex = dn.IndexOf("=", 1);
                    commaIndex = dn.IndexOf(",", 1);
                    if (-1 == equalsIndex)
                    {
                        return null;
                    }
                    groupNames.Append(dn.Substring((equalsIndex + 1),
                                (commaIndex - equalsIndex) - 1));
                    groupNames.Append("|");
                }

            return groupNames.ToString();

il suffit de coller les noms de groupe dans la chaîne de noms de groupe, pipe délimitée, mais quand vous tournez à travers, vous pouvez faire ce que vous voulez avec eux

24
répondu curtisk 2010-12-16 12:19:30

vous devez utiliser le système .DirectoryServices.AccountManagement . Il est beaucoup plus facile. Voici un projet de code de nice article vous donnant un aperçu sur toutes les classes dans cette DLL.

comme vous l'avez souligné, votre approche actuelle ne trouve pas le groupe primaire. En fait, c'est bien pire que ce que tu pensais. Il y a d'autres cas où cela ne fonctionne pas, comme le groupe local du domaine d'un autre domaine. Vous pouvez vérifier ici pour plus de détails. Voici à quoi ressemble le code si vous changez pour utiliser le système.DirectoryServices.AccountManagement. Le code suivant permet de trouver les groupes immédiats auxquels cet utilisateur s'est assigné, ce qui inclut le groupe primaire.

UserPrincipal user = UserPrincipal.FindByIdentity(new PrincipalContext (ContextType.Domain, "mydomain.com"), IdentityType.SamAccountName, "username");
foreach (GroupPrincipal group in user.GetGroups())
{
    Console.Out.WriteLine(group);
}
34
répondu Harvey Kwok 2015-08-21 12:37:10

Use tokenGroups :

DirectorySearcher ds = new DirectorySearcher();
ds.Filter = String.Format("(&(objectClass=user)(sAMAccountName={0}))", username);
SearchResult sr = ds.FindOne();

DirectoryEntry user = sr.GetDirectoryEntry();
user.RefreshCache(new string[] { "tokenGroups" });

for (int i = 0; i < user.Properties["tokenGroups"].Count; i++) {
    SecurityIdentifier sid = new SecurityIdentifier((byte[]) user.Properties["tokenGroups"][i], 0);
    NTAccount nt = (NTAccount)sid.Translate(typeof(NTAccount));
    //do something with the SID or name (nt.Value)
}

Note: Ceci n'obtient que des groupes de sécurité

22
répondu Shurdoof 2010-12-16 12:17:58

l'exemple suivant est tiré de L'article du projet de Code, (presque) tout dans Active Directory via C# :

// userDn is a Distinguished Name such as:
// "LDAP://CN=Joe Smith,OU=Sales,OU=domain,OU=com"
public ArrayList Groups(string userDn, bool recursive)
{
    ArrayList groupMemberships = new ArrayList();
    return AttributeValuesMultiString("memberOf", userDn,
        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;
}

il suffit d'appeler le groupes méthode avec le nom distinctif pour l'utilisateur, et passer dans le drapeau de bool pour indiquer si vous voulez inclure emboîtés / groupes d'enfants dans votre Arrayylist résultant:

ArrayList groups = Groups("LDAP://CN=Joe Smith,OU=Sales,OU=domain,OU=com", true);
foreach (string groupName in groups)
{
    Console.WriteLine(groupName);
}

si vous avez besoin de faire niveau sérieux de la programmation Active Directory en .NET je recommande vivement bookmarking & examiner L'article du projet de Code que j'ai mentionné ci-dessus.

1
répondu Saul Dolgin 2010-12-16 12:50:37

ce code fonctionne encore plus vite (deux 1,5 plus vite que ma version précédente):

    public List<String> GetUserGroups(WindowsIdentity identity)
    {
        List<String> groups = new List<String>();

        String userName = identity.Name;
        int pos = userName.IndexOf(@"\");
        if (pos > 0) userName = userName.Substring(pos + 1);

        PrincipalContext domain = new PrincipalContext(ContextType.Domain, "riomc.com");
        UserPrincipal user = UserPrincipal.FindByIdentity(domain, IdentityType.SamAccountName, userName); // NGeodakov

        DirectoryEntry de = new DirectoryEntry("LDAP://RIOMC.com");
        DirectorySearcher search = new DirectorySearcher(de);
        search.Filter = "(&(objectClass=group)(member=" + user.DistinguishedName + "))";
        search.PropertiesToLoad.Add("cn");
        search.PropertiesToLoad.Add("samaccountname");
        search.PropertiesToLoad.Add("memberOf");

        SearchResultCollection results = search.FindAll();
        foreach (SearchResult sr in results)
        {
            GetUserGroupsRecursive(groups, sr, de);
        }

        return groups;
    }

    public void GetUserGroupsRecursive(List<String> groups, SearchResult sr, DirectoryEntry de)
    {
        if (sr == null) return;

        String group = (String)sr.Properties["cn"][0];
        if (String.IsNullOrEmpty(group))
        {
            group = (String)sr.Properties["samaccountname"][0];
        }
        if (!groups.Contains(group))
        {
            groups.Add(group);
        }

        DirectorySearcher search;
        SearchResult sr1;
        String name;
        int equalsIndex, commaIndex;
        foreach (String dn in sr.Properties["memberof"])
        {
            equalsIndex = dn.IndexOf("=", 1);
            if (equalsIndex > 0)
            {
                commaIndex = dn.IndexOf(",", equalsIndex + 1);
                name = dn.Substring(equalsIndex + 1, commaIndex - equalsIndex - 1);

                search = new DirectorySearcher(de);
                search.Filter = "(&(objectClass=group)(|(cn=" + name + ")(samaccountname=" + name + ")))";
                search.PropertiesToLoad.Add("cn");
                search.PropertiesToLoad.Add("samaccountname");
                search.PropertiesToLoad.Add("memberOf");
                sr1 = search.FindOne();
                GetUserGroupsRecursive(groups, sr1, de);
            }
        }
    }
1
répondu Nuren Geodakov 2015-10-30 12:32:23

voici le code qui a fonctionné pour moi:

public ArrayList GetBBGroups(WindowsIdentity identity)
{
    ArrayList groups = new ArrayList();

    try
    {
        String userName = identity.Name;
        int pos = userName.IndexOf(@"\");
        if (pos > 0) userName = userName.Substring(pos + 1);

        PrincipalContext domain = new PrincipalContext(ContextType.Domain, "riomc.com");
        UserPrincipal user = UserPrincipal.FindByIdentity(domain, IdentityType.SamAccountName, userName);

        DirectoryEntry de = new DirectoryEntry("LDAP://RIOMC.com");
        DirectorySearcher search = new DirectorySearcher(de);
        search.Filter = "(&(objectClass=group)(member=" + user.DistinguishedName + "))";
        search.PropertiesToLoad.Add("samaccountname");
        search.PropertiesToLoad.Add("cn");

        String name;
        SearchResultCollection results = search.FindAll();
        foreach (SearchResult result in results)
        {
            name = (String)result.Properties["samaccountname"][0];
            if (String.IsNullOrEmpty(name))
            {
                name = (String)result.Properties["cn"][0];
            }
            GetGroupsRecursive(groups, de, name);
        }
    }
    catch
    {
        // return an empty list...
    }

    return groups;
}

public void GetGroupsRecursive(ArrayList groups, DirectoryEntry de, String dn)
{
    DirectorySearcher search = new DirectorySearcher(de);
    search.Filter = "(&(objectClass=group)(|(samaccountname=" + dn + ")(cn=" + dn + ")))";
    search.PropertiesToLoad.Add("memberof");

    String group, name;
    SearchResult result = search.FindOne();
    if (result == null) return;

    group = @"RIOMC\" + dn;
    if (!groups.Contains(group))
    {
        groups.Add(group);
    }
    if (result.Properties["memberof"].Count == 0) return;
    int equalsIndex, commaIndex;
    foreach (String dn1 in result.Properties["memberof"])
    {
        equalsIndex = dn1.IndexOf("=", 1);
        if (equalsIndex > 0)
        {
            commaIndex = dn1.IndexOf(",", equalsIndex + 1);
            name = dn1.Substring(equalsIndex + 1, commaIndex - equalsIndex - 1);
            GetGroupsRecursive(groups, de, name);
        }
    }
}

j'ai mesuré ses performances dans une boucle de 200 passages contre le code qui utilise la méthode récursive AttributeValuesMultiString ; et ça a fonctionné 1,3 fois plus vite. Peut-être à cause de nos paramètres publicitaires. Les deux bribes ont donné le même résultat.

1
répondu Nuren Geodakov 2016-02-26 09:27:24
PrincipalContext pc1 = new PrincipalContext(ContextType.Domain, "DomainName", UserAccountOU, UserName, Password);
UserPrincipal UserPrincipalID = UserPrincipal.FindByIdentity(pc1, IdentityType.SamAccountName, UserID);

searcher.Filter = "(&(ObjectClass=group)(member = " + UserPrincipalID.DistinguishedName + "));
0
répondu Dan W 2015-04-15 15:51:20

si vous avez une connexion LDAP avec un nom d'utilisateur et un mot de passe pour vous connecter à Active Directory, voici le code que j'ai utilisé pour me connecter correctement:

using System.DirectoryServices.AccountManagement;

// ...

// Connection information
var connectionString = "LDAP://domain.com/DC=domain,DC=com";
var connectionUsername = "your_ad_username";
var connectionPassword = "your_ad_password";

// Get groups for this user
var username = "myusername";

// Split the LDAP Uri
var uri = new Uri(connectionString);
var host = uri.Host;
var container = uri.Segments.Count() >=1 ? uri.Segments[1] : "";

// Create context to connect to AD
var princContext = new PrincipalContext(ContextType.Domain, host, container, connectionUsername, connectionPassword);

// Get User
UserPrincipal user = UserPrincipal.FindByIdentity(princContext, IdentityType.SamAccountName, username);

// Browse user's groups
foreach (GroupPrincipal group in user.GetGroups())
{
    Console.Out.WriteLine(group.Name);
}
0
répondu Maxime 2015-08-21 13:49:26