LDAP_MATCHING_RULE_IN_CHAIN 不适用于默认 AD 组 - 域用户 [英] LDAP_MATCHING_RULE_IN_CHAIN not working with default AD groups - Domain Users

查看:33
本文介绍了LDAP_MATCHING_RULE_IN_CHAIN 不适用于默认 AD 组 - 域用户的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

在我的程序中,我需要获取用户的所有 AD 组.我的程序的当前版本使用 System.DirectoryServices.AccountManagement.UserPrincipal.GetAuthorizationGroups.

In my program, I need to fetch all the AD groups for a user. The current version of my program uses System.DirectoryServices.AccountManagement.UserPrincipal.GetAuthorizationGroups.

这一直有效,直到我们有了一个 AD 更大的新客户.那里真的很慢.(最长 60 秒)

This works good until we had a new customer with a much largeer AD. There it is really slow. (Up to 60 seconds)

现在环顾四周,看到AccountManagement 好用,但速度慢的帖子.

Now I've been looking around, and saw the posts that the AccountManagement is easy to use, but slow.

我还发现 LDAP_MATCHING_RULE_IN_CHAIN 还应该获取用户所属的所有嵌套组.并且性能更高.

I also found that LDAP_MATCHING_RULE_IN_CHAIN should also fetch all the nested groups that a user is member of. And is more performant.

来自 链接.

但是我遇到了 AD 中存在的默认组的问题.

But I'm having an issue with the default groups that in AD exists.

例如,该函数不返回域用户"组.他们还有一个组BDOC",作为成员有域用户".该组也不返回.

For example the group "Domain Users" is not returned by the function. They also have a group "BDOC" that as member have "Domain Users". That group is also not returned.

通过 GetAuthorizationGroups 返回正确.

Trough the GetAuthorizationGroups it is returned correct.

我正在使用以下代码按用户获取组.

I'm using following code to fetch the groups by user.

VB.NET:

Dim strFilter As String = String.Format("(member:1.2.840.113556.1.4.1941:={0})", oUserPrincipal.DistinguishedName)
Dim objSearcher As New DirectoryServices.DirectorySearcher("LDAP://" & oLDAPAuthenticationDetail.Domain & If(Not String.IsNullOrWhiteSpace(oLDAPAuthenticationDetail.Container), oLDAPAuthenticationDetail.Container, String.Empty))
objSearcher.PageSize = 1000
objSearcher.Filter = strFilter
objSearcher.SearchScope = DirectoryServices.SearchScope.Subtree
objSearcher.PropertiesToLoad.Add(sPropGuid)
objSearcher.PropertiesToLoad.Add(sPropDisplayName)


Dim colResults As DirectoryServices.SearchResultCollection = objSearcher.FindAll()

之后,我使用链接中的脚本进行测试,是否可以通过将过滤器中的成员"更改为memberOf"来获取域用户组中的所有用户.当我将域管理员组放入过滤器时,它显示管理员是正确的.当我将域用户组放入过滤器时,它什么都不返回.

Afterwards I was testing with the script from the link, if it was possible to fetch all the users from the Domain Users group, by changing the "member" to "memberOf" in the filter. When I put the Domain Admins group in the filter, it shows the admins correct. When I put the Domain Users group in the filter, it returns nothing.

Powershell:

$userdn = 'CN=Domain Users,CN=Users,DC=acbenelux,DC=local'
$strFilter = "(memberOf:1.2.840.113556.1.4.1941:=$userdn)"
$objDomain = New-Object System.DirectoryServices.DirectoryEntry("LDAP://rootDSE")
$objSearcher = New-Object System.DirectoryServices.DirectorySearcher
$objSearcher.SearchRoot = "LDAP://$($objDomain.rootDomainNamingContext)"
$objSearcher.PageSize = 1000
$objSearcher.Filter = $strFilter
$objSearcher.SearchScope = "Base"
$colProplist = "name"
foreach ($i in $colPropList)
{
    $objSearcher.PropertiesToLoad.Add($i) > $nul
}
$colResults = $objSearcher.FindAll()
foreach ($objResult in $colResults)
{
    $objItem = $objResult.Properties
    $objItem.name
}

我不知道我做错了什么.或者可能只是无法使用该过滤器获取默认组"?那么什么是好的选择?

I don't know what I'm doing wrong. Or is it maybe just not possible to fetch the "default groups" with that filter? What is a good alternative then?

推荐答案

默认组是奇数.它不存储在 memberOf 中,甚至不存储在组的 member 属性中.这就是为什么您的搜索找不到它的原因.默认组由用户的 primaryGroupId 决定.该属性存储组的 RID(SID 的最后一部分).这有点愚蠢,我知道:)

The default group is odd. It is not stored in memberOf, or even in the member attribute of the group. That's why your search won't find it. The default group is determined by the primaryGroupId of the user. That attribute stores the RID (the last part of the SID) of the group. It's kind of dumb, I know :)

我实际上写了一篇关于某人成为群组成员的 3 种(是 3 种)不同方式的文章:什么使会员成为会员?

I actually wrote an article about the 3 (yes 3) different ways someone can be a member of a group: What makes a member a member?

我还写了一篇关于获取单个用户所属的所有组以及如何解释所有 3 种方式的文章:查找所有用户组

I also wrote an article about getting all of the groups a single user belongs to, and how to account for all 3 ways: Finding all of a user’s groups

例如,这是我在那篇文章中放置的 C# 代码,内容是关于如何查找用户的主要组的名称(给定 DirectoryEntry).将其转换为 VB.NET 应该不会太难:

For example, here is the C# code I put in that article about how to find the name of the primary group for a user (given a DirectoryEntry). It shouldn't be too hard to translate that to VB.NET:

private static string GetUserPrimaryGroup(DirectoryEntry de) {
    de.RefreshCache(new[] {"primaryGroupID", "objectSid"});

    //Get the user's SID as a string
    var sid = new SecurityIdentifier((byte[])de.Properties["objectSid"].Value, 0).ToString();

    //Replace the RID portion of the user's SID with the primaryGroupId
    //so we're left with the group's SID
    sid = sid.Remove(sid.LastIndexOf("-", StringComparison.Ordinal) + 1);
    sid = sid + de.Properties["primaryGroupId"].Value;

    //Find the group by its SID
    var group = new DirectoryEntry($"LDAP://<SID={sid}>");
    group.RefreshCache(new [] {"cn"});

    return group.Properties["cn"].Value as string;
}

您说得对,AccountManagement 命名空间使事情变得简单,但有时它的性能确实很差.我再也不用它了.我发现 DirectoryEntry/DirectorySearcher 可以让您更好地控制代码调用 AD 的频率.

You are right that the AccountManagement namespace makes things easy, but it really does have terrible performance sometimes. I never use it anymore. I find that DirectoryEntry/DirectorySearcher gives you much more control of how often your code makes calls out to AD.

我一直想写一篇关于使用 DirectoryEntry 编写高性能代码的文章,但我还没有开始.

I have been meaning to write an article about writing high performance code with DirectoryEntry, but I haven't gotten around to it yet.

更新: 因此,如果您需要用户的嵌套组,包括通过主要组的成员资格,那么您可以先找到主要组,然后执行 LDAP_MATCHING_RULE_IN_CHAIN 搜索具有这两个属性的组用户和主要组作为成员:

Update: So if you need the nested groups for the user, including membership through the primary group, then you can find the primary group first, then do an LDAP_MATCHING_RULE_IN_CHAIN search for groups that have both the user and the primary group as members:

 (|(member:1.2.840.113556.1.4.1941:={userDN})(member:1.2.840.113556.1.4.1941:={primaryGroupDN}))

更新:如果您想在搜索中包含 Authenticated Users(编辑 distinguishedNameDC 部分>):

Update: If you want to include Authenticated Users in your search (edit the DC portion of the distinguishedName):

 (|(member:1.2.840.113556.1.4.1941:=CN=S-1-5-11,CN=ForeignSecurityPrincipals,DC=domain,DC=com)(member:1.2.840.113556.1.4.1941:={userDN})(member:1.2.840.113556.1.4.1941:={primaryGroupDN})

请注意,您还可以使用用户的 tokenGroups 属性来查找用户的所有身份验证组.tokenGroups 属性是一个构造属性,因此只有在您明确要求时才能获得它(使用 DirectoryEntry.RefreshCache() 或者,在搜索中,将其添加到 DirectorySearcher.PropertiesToLoad.

Note that you can also use the tokenGroups attribute of a user to find out all of the authentication groups for a user. The tokenGroups attribute is a constructed attribute, so you only get it if you specifically ask for it (with DirectoryEntry.RefreshCache() or, in a search, add it to DirectorySearcher.PropertiesToLoad.

需要注意的是,tokenGroups 是一个 SID 列表,而不是 distinguishedName,但是您可以通过 LDAP:// 语法.

The caveat is that tokenGroups is a list of SIDs, not distinguishedName, but you can bind directly to an object using the SID with the LDAP://<SID={sid}> syntax.

这篇关于LDAP_MATCHING_RULE_IN_CHAIN 不适用于默认 AD 组 - 域用户的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆