我创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