我创建了一个WCF Web服务,用于从Active Directory返回用户和组信息。它适用于大多数群组和用户。
我使用directoryEntry.Invoke(“groups”,null)来返回指定用户所属的组。这将返回MOST组。奇怪的是我可以找到任何组并枚举其成员,即使它是我在其中一个成员上使用调用查询时丢失的组之一。
展示此行为的大多数组都启用了Exchange。大多数有问题的用户帐户都是针对联合域中的用户,他们在我查询的域中使用Exchange服务器。我不是在尝试查询联邦域中的对象。
到目前为止我的理论:
某些安全限制不允许通过invoke()枚举所有组,即使我可以查询缺少的组并枚举其成员。
invoke与某些子组有问题。也许通用,动态或启用Exchange的属性正在发挥作用
调用方法不会获取所有组,因为“联合”帐户(作为其Exchange帐户设置的一部分创建)与sid映射回登录域之外的常规域帐户有所不同。
答案 0 :(得分:6)
在DirectoryEntry上使用“Groups”属性有两个已知问题:
因此,如果用户是A组的成员,然后该组又是B组的成员,那么在Windows中,这意味着该用户也是B组的成员。但是,DirectoryEntry不会向您显示嵌套组成员资格。
对于直接Active Directory(没有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)”调用?为什么不直接枚举多值(包含多个值)并且包含组的DN(可分辨名称)的DirectoryEntry.Properties [“memberOf”]属性?
foreach(string groupDN in myUser.Properties["memberOf"])
{
string groupName = groupDN;
}
如果您使用的是.NET 3.5,则可以使用S.DS.AccountManagement中的新安全主体类。其中一个是“UserPrincipal”,它有一个名为“GetAuthorizationGroups()”的方法,它可以为你完成所有这些工作 - 基本上是免费的!
请参阅一篇优秀的MSDN article,其中介绍了这些新的.NET 3.5 S.DS功能。
答案 1 :(得分:0)
我认为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可能需要很长时间才能完成。
答案 2 :(得分:0)
弗雷德,
我正在尝试使用您的代码而不是走得太远。我已将目录条目路径更新为“LDAP:// DC = myDomain,DC = co,DC = uk”但我没有得到任何结果(obj.Properties [“tokenGroups”]。Count = 0)
我不知道如何指定列出组的用户。
你能指点我正确的方向吗?
由于
编辑:
我最后把它分类了。从中获取令牌组的目录条目应该是用户条目......如果这有意义......
我已经包含了一些代码,以防其他人有相同的查询:
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