简体   繁体   中英

How to get indirect groups of an AD user? - C#

I'm using DirectorySearcher to get the groups of an AD user in which he is a member of using the 'memberof' property. But according to this msdn page the 'memberof' property only returns the direct groups in which the user is a member. How can I get the indirect groups of the user too.

For ex.

Group A -> User X, User Y, Group B
Group B -> User Z
Group C -> User Z

I want to get the result as Group A, Group B, Group C for the user Z since he is an indirect user of Group A.

Update

Okie. I've followed this codeproject article to get the groups recursively. But still the builtin group 'Domain Users' is missing from the list. So does that mean Built in groups wont appear in the directory searcher?

The primary group of the user won't be shown in the "memberOf" property. Instead, it's RID is stored in the "primaryGroupID" property, and you have to calculate the group's SID from that RID (which is domain SID+group RID).

Thats why you couldn't find the Domain Users group (which is the user's primary group)

You have to define your own method of iterating through the direct groups until you reach the common root for all. You will need to perform an LDAP query against each group and use the same memberOf attribute to determine which groups that group belongs to. This can be time intensive, particularly if the groups are numerous and laid out web-like.

My answer follows the same lines as Joel Etherton's, but with code. I implemented this a while ago in one of my apps. All you need to do is interpret the VB.Net to C# :). The code below will take a group and return all of the child groups. So you just need to loop through for each group and put them in a list. I reference a few methods that I didn't include but should be self explanatory. I did include PrincipalGenericCollection, since it can be handy.

Public Function GetSubGroups(ByVal groupname As String) As List(Of String)
    Dim result As New List(Of String)()

    GetSubGroups(groupname, result)

    Return result
End Function

Public Sub GetSubGroups(ByVal Group As String, ByRef l As List(Of String))
    Dim grp = GetGroup(Group)

    'sometimes group will be null if its a system built in group like "authenticated users"'
    If grp Is Nothing Then
        Exit Sub
    End If

    Dim sGroups = GetGroupMembership(Group, False).Where(Function(c) TypeOf c Is GroupPrincipal)

    For Each g In sGroups
        Dim n As String = FormatPrincipalName(g.Name)

        If Not l.Contains(n) Then
            l.Add(n)

            GetSubGroups(g.Name, l)
        End If
    Next
End Sub

Public Function GetGroupMembership(ByVal GroupName As String, Optional ByVal Recursive As Boolean = True) As PrincipalGenericCollection(Of Principal)
    Dim group As GroupPrincipal = GetGroup(GroupName)

    If group Is Nothing Then
        Return Nothing
    End If

    Dim prinCol As New PrincipalGenericCollection(Of Principal)(group.GetMembers(Recursive))

    prinCol.SortByName()

    Return prinCol
End Function


Public Class PrincipalGenericCollection(Of T As Principal)
    Inherits List(Of T)

    Public Sub New()
        MyBase.New()
    End Sub

    Public Sub New(ByVal collection As PrincipalCollection)
        For Each p As Principal In collection
            Me.Add(p)
        Next
    End Sub

    Public Sub New(ByVal collection As IEnumerable(Of T))
        MyBase.New(collection)
    End Sub

    Public Sub SortByName()
        Sort(New PrincipalSorter(Of T))
    End Sub
End Class

Sounds to me like a simple recursive approach. Find the groups, the user is member of and for each group, find the groups, the group is member of. Repeat until no more memberships are found.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM