DirectoryEntry.Invoke(“组”,null)不检索所有组?

我创build了一个WCF Web服务来从Active Directory返回用户和组信息。 它适用于大多数组和用户。

我使用directoryEntry.Invoke(“groups”,null)返回指定用户所属的组。 这返回MOST组。 奇怪的是,我可以find任何组并枚举它的成员,即使它是我在其成员中使用调用查询时缺less的组之一。

大多数展示此行为的组都是启用了Exchange的。 大多数有问题的用户帐户是在联合域中的用户,他们在我查询的域中使用Exchange服务器。 我不想查询联合域中的对象。

我的理论到目前为止:

  • 一些安全限制不允许通过invoke()枚举所有组,即使我可以查询缺失的组并枚举它们的成员。

  • 调用与一些组的子集有问题。 也许通用的,dynamic的或支持Exchange的属性正在发挥作用

  • invoke方法没有select所有的组,因为“联合”帐户(作为他们的Exchange帐户设置的一部分创build的)与sid映射回其login域之外的普通域帐户不同。

在DirectoryEntry上使用“组”属性有两个已知问题:

  • 它不会向您显示用户所在的“默认组”(通常是“用户”)
  • 它不会显示你的嵌套组成员

因此,如果用户是组A的成员,而该组又是B组的成员,则在Windows中,这意味着该用户也是组B的成员。但是,DirectoryEntry不会向您显示嵌套组会员。

这些是我知道的两个直接活动目录(没有Exchange)的限制。

获取默认组是有点涉及,但我有一个代码示例。

private string GetPrimaryGroup(DirectoryEntry aEntry, DirectoryEntry aDomainEntry) { int primaryGroupID = (int)aEntry.Properties["primaryGroupID"].Value; byte[] objectSid = (byte[])aEntry.Properties["objectSid"].Value; StringBuilder escapedGroupSid = new StringBuilder(); // Copy over everything but the last four bytes(sub-authority) // Doing so gives us the RID of the domain for(uint i = 0; i < objectSid.Length - 4; i++) { escapedGroupSid.AppendFormat("\\{0:x2}", objectSid[i]); } //Add the primaryGroupID to the escape string to build the SID of the primaryGroup for(uint i = 0; i < 4; i++) { escapedGroupSid.AppendFormat("\\{0:x2}", (primaryGroupID & 0xFF)); primaryGroupID >>= 8; } //Search the directory for a group with this SID DirectorySearcher searcher = new DirectorySearcher(); if(aDomainEntry != null) { searcher.SearchRoot = aDomainEntry; } searcher.Filter = "(&(objectCategory=Group)(objectSID=" + escapedGroupSid.ToString() + "))"; searcher.PropertiesToLoad.Add("distinguishedName"); return searcher.FindOne().Properties["distinguishedName"][0].ToString(); } 

获取嵌套组还需要几个步骤,如果这是问题,我将不得不寻找解决方案。

渣子

PS:作为一个方面说明 – 为什么你在做一个“DirectoryEntry.Invoke(”groups“,null)”调用? 为什么不直接枚举多值(包含多个值)的DirectoryEntry.Properties [“memberOf”]属性,并在其中包含组的DN(专有名称)?

 foreach(string groupDN in myUser.Properties["memberOf"]) { string groupName = groupDN; } 

或者如果你使用.NET 3.5,你可以使用S.DS.AccountManagement中的新安全主体类。 其中之一是一个“UserPrincipal”,它有一个名为“GetAuthorizationGroups()”的方法,它为你做了所有这些努力 – 基本上是免费的!

看到一个很好的MSDN文章 ,为您描述这些新的.NET 3.5 S.DS功能。

我认为marc_s是正确的。 如果你想要所有的组,你可以使用下面的代码片段:

 using (DirectoryEntry obj = new DirectoryEntry("LDAP://" + dn)) { obj.RefreshCache(new string[] { "tokenGroups" }); string[] sids = new string[obj.Properties["tokenGroups"].Count]; int i = 0; foreach (byte[] bytes in obj.Properties["tokenGroups"]) { sids[i] = _ConvertSidToString(bytes); ++i; } obj.Close(); return sids; } 

请注意,计算嵌套组是一个昂贵的操作,因此RefreshCache可能需要很长时间才能完成。

在弗罗因德,

我正在试图利用你的代码,而不是很远。 我已经更新目录条目路径为“LDAP:// DC = myDomain,DC = co,DC = uk”,但我没有得到任何结果(obj.Properties [“tokenGroups”]。Count = 0)

我不udnerstand如何指定用户列表组。

你能指点我正确的方向吗?

谢谢

编辑:

最后我把它整理了一下。 获取令牌组的目录条目应该是一个用户条目…如果这是有道理的…

我已经包含了一些代码,以防其他人有相同的查询:

 Dim directoryEntry As DirectoryEntry = _ New DirectoryEntry("LDAP://CN=users,DC=domanName,DC=com") Dim directorySearcher As DirectorySearcher = _ New DirectorySearcher(directoryEntry, "(sAMAccountName=" & UserName & ")") Dim searchResult As SearchResult = directorySearcher.FindOne() If Not searchResult Is Nothing Then Dim userDirectoryEntry As DirectoryEntry = searchResult.GetDirectoryEntry userDirectoryEntry.RefreshCache(New String() {"tokenGroups"}) ... etc ... End If