2011-04-21 34 views
0

我使用Active Directory中枚舉域本地組:ActiveDs.IADsMembers - 枚舉全局組包含一個外部安全主體

Dim de As New DirectoryEntry("path") 
Dim members As IADsMembers = DirectCast(de.Invoke("Members"), IADsMembers) 

members.Filter = New Object() {"user"} 
'Iterate over users. 
members.Filter = New Object() {"group"} 
'Iterate over nested groups. 

域本地組不枚舉。我檢查了members.Count等於1.

查看Active Directory中有一個外部安全主體,它鏈接到另一個域中的全局組。研究表明,members.Filter的唯一選項是user and group,usergroup

如何從此集合中提取外部安全主體?

回答

2

大多數情況下,我選擇使用.NET 3.5中的System.Directory.AccountManagement提供的功能來枚舉全局組。如果被枚舉的對象實際上是一個外部安全主體,那麼.NET 3.5代碼是不夠的。希望下面的代碼將幫助別人:

Private Sub EnumerateGlobalGroup(ByVal distinguishedName As String) 

    Try 

     Using context As New PrincipalContext(ContextType.Domain, GetDomainName(distinguishedName)) 
      Using gp As GroupPrincipal = GroupPrincipal.FindByIdentity(context, IdentityType.DistinguishedName, distinguishedName) 
       Dim groupMembers As PrincipalSearchResult(Of Principal) = gp.GetMembers(True) 
       For Each member As Principal In groupMembers 

        Console.WriteLine(member.DisplayName) 
        Select Case member.StructuralObjectClass 
         Case "user" 
          Console.WriteLine("user") 
         Case "group" 
          Console.WriteLine("group") 
        End Select 

       Next 
      End Using 
     End Using 

    Catch ex As Exception 

     If Not TypeOf ex Is PrincipalOperationException Then Throw ex 

     'Get this far then enumerating Foreign Security Principal. 
     Dim groupEntry As New DirectoryEntry("LDAP://" & distinguishedName) 
     Dim members As Object = groupEntry.Invoke("Members") 
     For Each member As Object In CType(members, IEnumerable) 
      Dim memberEntry As New DirectoryEntry(member) 
      Console.WriteLine(memberEntry.Name) 

      Dim sid As New SecurityIdentifier(DirectCast(memberEntry.InvokeGet("objectSid"), Byte()), 0) 
      Dim account As NTAccount = sid.Translate(GetType(NTAccount)) 
      Console.WriteLine(account.ToString) 

      Dim memberDistinguishedName As String = GetDistinguishedName(account.ToString) 
      EnumerateGlobalGroup(memberDistinguishedName) 
     Next 

    End Try 

End Sub 

Private Function GetDomainName(ByVal dn As String) As String 

    Dim dnParts As String() = dn.Split(Char.Parse(",")) 
    For Each d As String In dnParts 
     If d.StartsWith("DC") Then Return d.ToUpper().Replace("DC=", Nothing) 
    Next 
    Return Nothing 

End Function 

Private Function GetDistinguishedName(ByVal accountName As String) As String 

    Dim nameTranslate = New ActiveDs.NameTranslate() 
    nameTranslate.Set(ActiveDs.ADS_NAME_TYPE_ENUM.ADS_NAME_TYPE_NT4, accountName) 

    Return nameTranslate.Get(ActiveDs.ADS_NAME_TYPE_ENUM.ADS_NAME_TYPE_1779) 

End Function 

有這樣的可能是更好的方式,但它的工作原理

1

您的域中有foreign security principal這一事實表明您的組成員實際上來自另一個森林。您需要確保您用於運行代碼的帳戶有權訪問其他林。

如果您使用的是.NET 3.5或更高版本,則應該嘗試使用System.DirectoryService.AccountManagement

我認爲GroupPrincipal.GetMembers應該可以解決你的問題。這MSDN link包括如何使用此GroupPrincipal示例。它允許你指定遞歸地獲取成員。它還提到你可以從不同的森林中獲得成員。

+0

我很高興能夠在.NET 3.5中使用所有這些漂亮的包裝器,這讓我感到很沮喪。如果全局組包含FSP,則發現FindByIdentity失敗。 – youwhut 2011-05-12 09:04:44