Wie kann ich prüfen, ob ein Benutzer Mitglied einer Gruppe im Active Directory ist?

Wem es so ergangen ist wie mir und gedacht hat, ist doch ganz einfach:
Ich instanziere ein neues System.DirectoryServices.AccountManagement.UserPrincipal und prüfe mit der Methode IsMemberOf, ob der Benutzer ein Mitglied der Gruppe ist, der täuscht sich!

Was zunächst relativ trivial erscheint, entpuppt sich als relativ verzwickt, wenn man mit Untergruppen arbeitet, denn dann gibt die Methode false zurück, obwohl man Mitglied einer solchen Gruppe ist.

Und genau das ist auch das Verzwickte daran, denn es wird klappen, wenn man nach der Gruppe prüft, welche direkt dem Benutzer zugewiesen wurde, jedoch das Prüfen auf Mitgliedschaft einer “Gruppe einer Gruppe” wird ein falsches Ergebnis zurückgeben, nämlich immer false.

Anbei ein Beispiel, wie so eine Hierarchie in der Praxis aussehen könnte:

Gruppe “Alle Benutzer von Firma …”

Gruppe “Alle Benutzer der Abteilung …”

Gruppe “Alle Benutzer der Abteilung … am Standort …

Benutzer “Hans Mustermann”

Ruft man nun

string userName = "HMustermann";         // Benutzer "Hans Mustermann"
string groupName = "MusterfirmaAlle";    // Gruppe "Alle Benutzer von Firma ..."

var pc = new PrincipalContext(ContextType.Domain);
var adUser = UserPrincipal.FindByIdentity(pc, userName);
var adGroup = GroupPrincipal.FindByIdentity(pc, groupName);

bool isMember = adUser.IsMemberOf(adGroup);

auf, wird man überrascht feststellen, dass isMember false ist.

Was man nun also tun muss ist die Untergruppen durchtraversieren und jeweils überprüfen, ob der Benutzer Mitglied dieser Gruppe ist.

Dies kann mit folgendem Code einfach erreicht werden:

private static IEnumerable<GroupPrincipal> GetGroupPrincipalsRecursive(
    GroupPrincipal groupPrincipal)
{
    yield return groupPrincipal;
    foreach (var subGroup in groupPrincipal.GetMembers()
        .OfType<GroupPrincipal>())
    {
        foreach (var subSubGroup in GetGroupPrincipalsRecursive(subGroup))
            yield return subSubGroup;
    }
}

Nun kann man folgendermaßen überprüfen ob es sich um ein gültiges Mitglied handelt:

bool isMember = GetGroupPrincipalsRecursive(adGroup)
    .Any(g => adUser.IsMemberOf(g));

Extension-Method

Da ich Erweiterungsmethoden liebe, hier ein weiteres Beispiel einer Implementierung:

static class UserPrincipalExt
{
    public static bool IsMemberOfRecursive(this UserPrincipal user, GroupPrincipal group)
    {
        return GetGroupPrincipalsRecursive(group)
            .Any(g =>
            {
                try { return user.IsMemberOf(g); }
                catch (PrincipalOperationException) { return false; }
            });
    }

    private static IEnumerable<GroupPrincipal> GetGroupPrincipalsRecursive(
        GroupPrincipal groupPrincipal)
    {
        yield return groupPrincipal;
        foreach (var subGroup in groupPrincipal.GetMembers()
            .OfType<GroupPrincipal>())
        {
            foreach (var subSubGroup in GetGroupPrincipalsRecursive(subGroup))
                yield return subSubGroup;
        }
    }
}

Verwendung:

bool isMember = adUser.IsMemberOfRecursive(adGroup);
Tagged , ,

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

%d bloggers like this: