【问题标题】:How best to recursively query AD Group membership in ASP.NET (using vb)如何最好地在 ASP.NET 中递归查询 AD 组成员身份(使用 vb)
【发布时间】:2012-10-24 23:52:33
【问题描述】:

我正在尝试通过以下两种方式之一找到查询 Active Directory 的最简单方法:

  1. 给定一个 AD 用户名,查找该用户所属的所有组(包括嵌套组)。

  2. 给定一个 AD 组名称,查找属于该组的所有用户(包括嵌套组中的用户)。

我的应用程序位于 v4.0 框架上的 VB.NET 中。我查看了来自许多不同 Google 搜索结果的建议,其中一些使用了 LDAP 和 System.DirectoryServices.DirectorySearcher(我认为这可能是最佳途径)。

但我正在寻找代码示例。

谢谢。

更新:

我已经准备好这些部分了:

<add assembly="System.DirectoryServices, Version=3.5.0.0, etc."/>

<add namespace="System.DirectoryServices.AccountManagement" />Imports System.DirectoryServices.AccountManagement

在这行代码上:

Dim ctx As New PrincipalContext(ContextType.Domain)

我仍然收到此错误:Type 'PrincipalContext' is not defined

当您提到“using 语句”时,我假设您的意思是我需要引用此命名空间。还是你的意思是我应该这样做?

Using ctx As New PrincipalContext(ContextType.Domain)

【问题讨论】:

    标签: asp.net vb.net recursion active-directory ldap


    【解决方案1】:

    一个完整的例子

    此代码将通过枚举给定的组名称列出组和子组中的所有用户。 此外,如果启用/禁用了用户帐户。

    要使用,只需调用 ListADGroupMembers("Some_Group_Name")。 这会将用户的全名和手机号码填充到一个数组中,然后您可以循环访问。

    很容易理解,只需通读即可。

    Public ADUSers(,) As String
     Public n As Integer = 0
    
     Public Sub ListADGroupMembers(ByVal GN As String)
    
        Dim DirectoryRoot As New DirectoryEntry("LDAP://RootDSE")
        Dim DNC = DirectoryRoot.Properties("DefaultNamingContext")(0).ToString()
        Dim GroupName As String = GN '"G_All_IT_Users"
        Dim GroupMembers As System.Collections.Specialized.StringCollection = GetGroupMembers(DNC, GroupName)
        'Dim GroupMembersMobile As System.Collections.Specialized.StringCollection = GetGroupMembers(DNC, GroupName)
        '  For Each Member As String In GroupMembers
        '    ListBox1.Items.Add(Member)
        'Next Member
    
    End Sub
    
    Public Function GetGroupMembers(ByVal strDomain As String, ByVal strGroup As String) As System.Collections.Specialized.StringCollection
    
        Dim GroupMembers As New System.Collections.Specialized.StringCollection()
    
        Try
            Dim DirectoryRoot As New DirectoryEntry("LDAP://" & strDomain)
            Dim DirectorySearch As New DirectorySearcher(DirectoryRoot, "(CN=" & strGroup & ")")
            Dim DirectorySearchCollection As SearchResultCollection = DirectorySearch.FindAll()
            For Each DirectorySearchResult As SearchResult In DirectorySearchCollection
                Dim ResultPropertyCollection As ResultPropertyCollection = DirectorySearchResult.Properties
                Dim GroupMemberDN As String
                For Each GroupMemberDN In ResultPropertyCollection("member")
                    Dim DirectoryMember As New DirectoryEntry("LDAP://" & GroupMemberDN)
                    Dim DirectoryMemberProperties As System.DirectoryServices.PropertyCollection = DirectoryMember.Properties
                    Dim DirectoryItem As Object = DirectoryMemberProperties("sAMAccountName").Value
                    Dim DirectoryPhone As Object = DirectoryMemberProperties("mobile").Value
                    Dim uac As Object = DirectoryMemberProperties("userAccountControl").Value
    
                    If DirectoryMember.SchemaClassName = "group" Then
                        ' this is a group.                        
                        ListADGroupMembers(DirectoryItem)
                    End If
    
                    If DirectoryMember.SchemaClassName = "user" Then
                        ' this is a user.
                        If Nothing IsNot DirectoryItem Then
                            If AccEnabled(uac) = 1 Then ' check the ad account is enabled
                                GroupMembers.Add(DirectoryItem.ToString())
                                ListBox1.Items.Add(DirectoryItem.ToString() & " " & DirectoryPhone)
    
                                ADUSers(0, n) = DirectoryItem.ToString()
                                ADUSers(1, n) = DirectoryPhone
                                n += 1
                                ReDim Preserve ADUSers(1, n)
                            End If
                        End If
                    End If
    
                Next GroupMemberDN
    
            Next DirectorySearchResult
        Catch ex As Exception
            MsgBox(ex.Message)
        End Try
    
        Return GroupMembers
    
    
    
    End Function
    
    
    
    
      ' check account is active or not.
    Function AccEnabled(ByVal uac As String) As String
    
        Dim aret As Integer = 0
        Select Case uac
            Case 512 'Enabled 
                aret = 1
            Case 514 ': ACCOUNTDISABLE()
                aret = 0
            Case 528 ': Enabled(-LOCKOUT)
                aret = 1
            Case 530 ': ACCOUNTDISABLE(-LOCKOUT)
                aret = 0
            Case 544 ': Enabled(-PASSWD_NOTREQD)
                aret = 1
            Case 546 ': ACCOUNTDISABLE(-PASSWD_NOTREQD)
                aret = 0
            Case 560 ': Enabled(-PASSWD_NOTREQD - LOCKOUT)
                aret = 1
            Case 640 ': Enabled(-ENCRYPTED_TEXT_PWD_ALLOWED)
                aret = 1
            Case 2048 ' : INTERDOMAIN_TRUST_ACCOUNT()
                aret = 1
            Case 2080 ': INTERDOMAIN_TRUST_ACCOUNT(-PASSWD_NOTREQD)
                aret = 1
            Case 4096 ': WORKSTATION_TRUST_ACCOUNT()
                aret = 1
            Case 8192 ': SERVER_TRUST_ACCOUNT()
                aret = 1
            Case 66048 ': Enabled(-DONT_EXPIRE_PASSWORD)
                aret = 1
            Case 66050 ': ACCOUNTDISABLE(-DONT_EXPIRE_PASSWORD)
                aret = 0
            Case 66064 ': Enabled(-DONT_EXPIRE_PASSWORD - LOCKOUT)
                aret = 1
            Case 66066 ': ACCOUNTDISABLE(-DONT_EXPIRE_PASSWORD - LOCKOUT)
                aret = 0
            Case 66080 ': Enabled(-DONT_EXPIRE_PASSWORD - PASSWD_NOTREQD)
                aret = 1
            Case 66082 ': ACCOUNTDISABLE(-DONT_EXPIRE_PASSWORD - PASSWD_NOTREQD)
                aret = 0
            Case 66176 ': Enabled(-DONT_EXPIRE_PASSWORD - ENCRYPTED_TEXT_PWD_ALLOWED)
                aret = 1
            Case 131584 ': Enabled(-MNS_LOGON_ACCOUNT)
                aret = 1
            Case 131586 ': ACCOUNTDISABLE(-MNS_LOGON_ACCOUNT)
                aret = 0
            Case 131600 ': Enabled(-MNS_LOGON_ACCOUNT - LOCKOUT)
                aret = 1
            Case 197120 ': Enabled(-MNS_LOGON_ACCOUNT - DONT_EXPIRE_PASSWORD)
                aret = 1
            Case 532480 'SERVER_TRUST_ACCOUNT - TRUSTED_FOR_DELEGATION (Domain Controller) 
                aret = 1
            Case 1049088 ': Enabled(-NOT_DELEGATED)
                aret = 1
            Case 1049090 ': ACCOUNTDISABLE(-NOT_DELEGATED)
                aret = 0
            Case 2097664 ': Enabled(-USE_DES_KEY_ONLY)
                aret = 1
            Case 2687488 ': Enabled(-DONT_EXPIRE_PASSWORD - TRUSTED_FOR_DELEGATION - USE_DES_KEY_ONLY)
                aret = 1
            Case 4194816 ': Enabled(-DONT_REQ_PREAUTH)
                aret = 1
            Case Else
                aret = 0
        End Select
    
        AccEnabled = aret
    
    End Function
    

    【讨论】:

    • 摇滚。非常感谢——你的代码极大地帮助了我。干得好。
    【解决方案2】:

    试试这个:

    ' set up domain context
    Dim ctx As New PrincipalContext(ContextType.Domain)
    
    ' find a user
    Dim user As UserPrincipal = UserPrincipal.FindByIdentity(ctx, "SomeUserName")
    
    If user IsNot Nothing Then
        Dim groupMemberships = user.GetAuthorizationGroups()
    
                ' do something with group....
        For Each gp As GroupPrincipal In groupMemberships
        Next
    End If
    

    您应该查看System.DirectoryServices.AccountManagement (S.DS.AM) 命名空间。在此处阅读所有相关信息:

    新的 S.DS.AM 让在 AD 中与用户和组一起玩变得非常容易!

    .GetAuthorizationGroups() 方法将进行递归搜索 - 因此您应该直接或间接获取用户所属的所有组。

    【讨论】:

    • 酷——我会试试这个。但是我不必定义 LDAP 路径吗?还是假设我使用的是<authentication mode="Windows" />...?
    • 我收到此错误:BC30002:未定义类型“PrincipalContext”。我已将其包含在 web.config 中:<add namespace="System.DirectoryServices.AccountManagement" /> 根据 MSDN,PrincipalContext 类是该 AccountManagement 类的一部分。我还需要包含其他命名空间/类吗?
    • 您是否看到我最近的评论:PrincipalContext 错误?有什么想法吗?
    • @Octavient:您是否也在使用PrincipalContext 的代码隐藏文件中包含了 using 语句?仅仅添加程序集是不够的......
    • 我已对我的原始帖子添加了更新,其中包含更具体的细节。希望你愿意帮助我看透这一切……?
    【解决方案3】:
    Imports System.Security.Principal
    
    Private Function GetGroups(userName As String) As List(Of String)
        Dim result As New List(Of String)
        Dim wi As WindowsIdentity = New WindowsIdentity(userName)
    
        For Each group As IdentityReference In wi.Groups
            Try
                result.Add(group.Translate(GetType(NTAccount)).ToString())
            Catch ex As Exception
            End Try
        Next
    
        result.Sort()
        Return result
    End Function
    

    所以只需使用 GetGroups("userID")。因为这种方法使用用户的 SID,所以没有进行显式 LDAP 调用。如果您使用自己的用户名,它将使用缓存的凭据,因此此功能非常快。

    Try Catch 是必要的,因为在大公司中,AD 非常大,以至于一些 SID 会迷失在太空中。

    https://stackoverflow.com/a/19403297/2886367

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2019-01-15
      • 2010-10-14
      • 1970-01-01
      相关资源
      最近更新 更多