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

发布于 2024-08-02 02:11:23 字数 557 浏览 10 评论 0原文

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

我使用directoryEntry.Invoke("groups",null) 返回指定用户所属的组。 这将返回 MOST 组。 奇怪的是,我可以找到任何组并枚举其成员,即使它是我在其成员之一上使用调用查询时丢失的组之一。

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

到目前为止我的理论:

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

  • invoke 对某些组子集存在问题。 也许通用、动态或支持 Exchange 的属性正在发挥作用

  • 调用方法不会选取所有组,因为“联合”帐户(作为其 Exchange 帐户设置的一部分创建)在某种程度上与超出范围的常规域帐户有所不同。 sid 映射回其登录域。

I created a WCF web service to return user and group information from Active Directory. It works for most groups and users.

I use directoryEntry.Invoke("groups",null) to return the groups a specified user is member of. This returns MOST groups. The odd thing is I can find any group and enumerate its members, even if it is one of the groups missing when I use the invoke query on one of its members.

Most of the groups that exhibit this behavior are Exchange-enabled. Most of the problematic user accounts are for users in a federated domain, who use an Exchange server in the domain that I query. I am not trying to query objects in the federated domain.

My theories so far:

  • some security restriction does not allow enumerating all groups via invoke() even though I can query missing groups and enumerate their members.

  • invoke has issues with some subset of groups. Perhaps universal, dynamic, or Exchange-enabled properties are at play

  • the invoke method does not pick up all groups because the "federated" accounts (created as part of their Exchange account setup) are somehow different than regular domain accounts beyond the sid mapping back to their login domain.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

月亮是我掰弯的 2024-08-09 02:11:23

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

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

因此,如果用户是成员组 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)”调用? 为什么不直接枚举 DirectoryEntry.Properties["memberOf"] 属性,该属性是多值(包含多个值)并且其中包含组的 DN(可分辨名称)?

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

或者,如果您使用 .NET 3.5,则可以使用 S.DS.AccountManagement 中的新安全主体类。 其中之一是“UserPrincipal”,它有一个名为“GetAuthorizationGroups()”的方法,它可以为您完成所有这些艰苦的工作 - 基本上是免费的!

请参阅描述这些新的 .NET 3.5 S.DS 的优秀 MSDN 文章为您提供的功能。

There are two known issues with using the "Groups" property on a DirectoryEntry:

  • it will not show you the "Default group" a user is in (typically "Users")
  • it will not show you nested group memberships

So if a user is member of a group A, and that group then in turn is member of Group B, then in Windows, this means that the user is also member of Group B. However, the DirectoryEntry will not show you that nested group membership.

Those are the two only restrictions I know of for straight Active Directory (without Exchange).

Getting the default group is a bit involved, but I do have a code sample for that.

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();
}

Getting the nested groups also takes a few steps and I'll have to hunt for a solution to that one, if that's the problem.

Marc

PS: as a side note - why on earth are you doing a "DirectoryEntry.Invoke("groups", null)" call? Why don't you just enumerate the DirectoryEntry.Properties["memberOf"] property which is multi-valued (contains multiple values) and has the group's DN (distinguished name) in it?

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

OR if you're on .NET 3.5, you can make use of the new Security Principal classes in S.DS.AccountManagement. One of them is a "UserPrincipal", which has a method called "GetAuthorizationGroups()" which does all this hard work for you - for free, basically!

See an excellent MSDN article that describes these new .NET 3.5 S.DS features for you.

清欢 2024-08-09 02:11:23

我认为 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 可能需要很长时间才能完成。

I think marc_s is correct. If you want all groups, you can use the following snippet:

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;
}

Note that calculating nested groups is an expensive operation, so RefreshCache might take a long time to complete.

赴月观长安 2024-08-09 02:11:23

关于弗罗因德,

我正在尝试利用你的代码,但没有走得太远。 我已将目录条目路径更新为“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

On Freund,

I am trying to make use of your code and not getting very far. I have updated the directory entry path to be "LDAP://DC=myDomain,DC=co,DC=uk" but I am not getting any results (obj.Properties["tokenGroups"].Count = 0)

I don't udnerstand how the user to list group for is specified.

Could you please point me in the right direction?

Thanks

EDIT:

I got it sorted in the end. The directory entry to get the token groups from should be a user entry... if that makes sense...

I've included some code in case anyone else has the same query:

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
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文