“域用户” 当我使用 DirectoryServices“member”时,组为空 财产

发布于 2024-07-13 20:33:30 字数 523 浏览 12 评论 0 原文

我使用以下代码来获取我的域中的组的成员:

  Dim de As New DirectoryEntry("LDAP://" & GroupDN)

  For Each user As String In CType(de.Properties("member"), IEnumerable)

          GroupCollection.Add(Username, Username)

  Next

我的问题是,当 GroupDN (组的专有名称)为“CN=Domain Users,CN=Users,DC=Mydomain,DC =local”,For...Each循环不执行,当我手动检查Properties语句时,它的计数为零。 这似乎适用于我域中的所有其他组,但“域用户”组应该包含所有人,但它似乎不包含任何人。

我已经检查过,该组在我的 Windows AD 工具中正确列出了每个人。 我在这里缺少什么明显的东西吗? 顺便说一句,是否有更好的方法来获取组中的所有成员?

I'm using the following code to get the members of a group on my domain:

  Dim de As New DirectoryEntry("LDAP://" & GroupDN)

  For Each user As String In CType(de.Properties("member"), IEnumerable)

          GroupCollection.Add(Username, Username)

  Next

My problem is that when GroupDN (the distinguishedname of the group) is "CN=Domain Users,CN=Users,DC=Mydomain,DC=local", the For...Each loop doesn't execute, and when I check the Properties statement manually, it's got a count of zero. This seems to work for every other group in my domain, but the "Domain Users" group should contain everybody, and it appears to contain nobody.

I've checked, and the group lists everybody correctly in my Windows AD tools. Is there something obvious that I'm missing here? On a side note, is there a better way to get all the members of a group?

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

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

发布评论

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

评论(2

飘落散花 2024-07-20 20:33:30

除非您更改用户的主组 ID,否则该用户不会存储在域用户组的成员属性中,而是使用主组 ID 设置为域用户 RID 的事实来确定域用户中的成员身份。 正常情况是Domain Users成员属性为空; 为了避免这种情况,您需要对默认的 Active Directory 实现进行一些更改。

域用户组使用
基于的“计算”机制
用户的“主要组 ID”
确定成员资格,并且不
通常将成员存储为
多值链接属性。 如果
用户的主要组已更改,
他们在域用户中的成员身份
组被写入链接
组的属性,并且是 no
计算时间较长。 这对于
Windows 2000 并没有改变
Windows Server 2003。

参考

Unless you change the primary group id of a user, the user is not stored in the member attribute of the Domain Users group, rather it uses the fact that the primary group id is set to the Domain Users RID to determine membership in Domain Users. The normal case is that the Domain Users member attribute is empty; it would require that you make some changes to the default Active Directory implementation for this to not be the case.

The Domain Users group uses a
"computed" mechanism based on the
"primary group ID" of the user to
determine membership and does not
typically store members as
multi-valued linked attributes. If the
primary group of the user is changed,
their membership in the Domain Users
group is written to the linked
attribute for the group and is no
longer calculated. This was true for
Windows 2000 and has not changed for
Windows Server 2003.

Reference

情魔剑神 2024-07-20 20:33:30

接受的答案绝对正确。 默认情况下,每个(用户)对象都在属性 513 ="nofollow noreferrer">primarygroupid,这是 域用户 sid。 但是:这可以更改,并且可以在那里配置所有其他组,因此我们不能依赖它。

以下是如何获取组成员的示例方法(无论默认值是保留还是更改)。 我在对 Active Directory 组的成员进行任何查询之后调用这样的方法。 在此示例中,我得到了一组可分辨名称作为结果。 但所有其他属性都是可能的,只需将它们添加到 dSearcher.PropertiesToLoad.Add(...) 并修改结果即可。

我知道,这是一个关于VB的问题,我希望它很容易移植。


    using System.DirectoryServices;
    using System.Security.Principal;


    public static string[] GetMembersDnByPrimaryGroupId(string domainName, SecurityIdentifier sidOfGroupToGetMembersByPrimaryGroupId)
    {
        // In a single domain environement the domain name is probably not needed, but
        // we expect a multy domain environement
        if (string.IsNullOrWhiteSpace(domainName) || sidOfGroupToGetMembersByPrimaryGroupId == null)
        {
            throw new ArgumentNullException($"Neither domainName nor sid may be null / blank: DomainName: { domainName }; sid: { sidOfGroupToGetMembersByPrimaryGroupId }");
            //<----------
        }

        List<string> membersDnResult = new List<string>();
        // Get the last segment of the group sid, this is what is stored in the "primaryGroupId"
        string groupSidTail = sidOfGroupToGetMembersByPrimaryGroupId.Value.Split('-').Last();
        string path = $"LDAP://{ domainName }";
        DirectoryEntry dEntry = new DirectoryEntry(path);

        SearchResultCollection adSearchResult = null;
        DirectorySearcher dSearcher = new DirectorySearcher(dEntry);

        // For this example we need just the distinguished name but you can add
        // here the property / properties you want
        dSearcher.PropertiesToLoad.Add("distinguishedName");

        // set the filter to primarygroupid
        dSearcher.Filter = $"(&(primarygroupid={ groupSidTail }))";

        // May die thousand deaths, therefore exception handling is needed. 
        // My exception handling is outside of this method, you may want
        // to add it here
        adSearchResult = dSearcher.FindAll();

        // Get the domains sid and check if the domain part of the wanted sid
        // fits the domain sid (necesarry in multy domain environments)
        byte[] domainSidBytes = (byte[])dEntry.Properties["objectSid"].Value;
        SecurityIdentifier domainSid = new SecurityIdentifier(domainSidBytes, 0);
        if (sidOfGroupToGetMembersByPrimaryGroupId.AccountDomainSid != domainSid)
        {
            throw new ArgumentException($"Domain sid of the wanted group { sidOfGroupToGetMembersByPrimaryGroupId.AccountDomainSid } does not fit the sid { domainSid } of the searched through domain \"{ domainName }\"");
            //<----------
        }

        // We found entries by the primarygroupid
        if (adSearchResult.Count > 0)
        {
            foreach (SearchResult forMemberByPrimaryGroupId in adSearchResult)
            {
                // Every AD object has a distinguishedName, therefore we acess "[0]" 
                // wihtout any further checking
                string dn = forMemberByPrimaryGroupId.Properties["distinguishedName"][0].ToString();
                membersDnResult.Add(dn);
            }
        }

        return membersDnResult.ToArray();
    }

The accepted answer is absolutely correct. By default every (user) object has 513 set in the property primarygroupid, which is the fixed "tail" of the Domain Users sid. But: this can be changed and every other group can be configured there, so we can't rely on that.

Here is an example method how to get the group members anyway (regardless if the default is kept or changed). I call a method like this after any query for members of active directory groups. In this example I get an array of distinguished names as result. But all other properties are possible, just add them to dSearcher.PropertiesToLoad.Add(...) and modify the result.

I know, this is a question about VB, I hope its easy to port it.


    using System.DirectoryServices;
    using System.Security.Principal;


    public static string[] GetMembersDnByPrimaryGroupId(string domainName, SecurityIdentifier sidOfGroupToGetMembersByPrimaryGroupId)
    {
        // In a single domain environement the domain name is probably not needed, but
        // we expect a multy domain environement
        if (string.IsNullOrWhiteSpace(domainName) || sidOfGroupToGetMembersByPrimaryGroupId == null)
        {
            throw new ArgumentNullException(
quot;Neither domainName nor sid may be null / blank: DomainName: { domainName }; sid: { sidOfGroupToGetMembersByPrimaryGroupId }");
            //<----------
        }

        List<string> membersDnResult = new List<string>();
        // Get the last segment of the group sid, this is what is stored in the "primaryGroupId"
        string groupSidTail = sidOfGroupToGetMembersByPrimaryGroupId.Value.Split('-').Last();
        string path = 
quot;LDAP://{ domainName }";
        DirectoryEntry dEntry = new DirectoryEntry(path);

        SearchResultCollection adSearchResult = null;
        DirectorySearcher dSearcher = new DirectorySearcher(dEntry);

        // For this example we need just the distinguished name but you can add
        // here the property / properties you want
        dSearcher.PropertiesToLoad.Add("distinguishedName");

        // set the filter to primarygroupid
        dSearcher.Filter = 
quot;(&(primarygroupid={ groupSidTail }))";

        // May die thousand deaths, therefore exception handling is needed. 
        // My exception handling is outside of this method, you may want
        // to add it here
        adSearchResult = dSearcher.FindAll();

        // Get the domains sid and check if the domain part of the wanted sid
        // fits the domain sid (necesarry in multy domain environments)
        byte[] domainSidBytes = (byte[])dEntry.Properties["objectSid"].Value;
        SecurityIdentifier domainSid = new SecurityIdentifier(domainSidBytes, 0);
        if (sidOfGroupToGetMembersByPrimaryGroupId.AccountDomainSid != domainSid)
        {
            throw new ArgumentException(
quot;Domain sid of the wanted group { sidOfGroupToGetMembersByPrimaryGroupId.AccountDomainSid } does not fit the sid { domainSid } of the searched through domain \"{ domainName }\"");
            //<----------
        }

        // We found entries by the primarygroupid
        if (adSearchResult.Count > 0)
        {
            foreach (SearchResult forMemberByPrimaryGroupId in adSearchResult)
            {
                // Every AD object has a distinguishedName, therefore we acess "[0]" 
                // wihtout any further checking
                string dn = forMemberByPrimaryGroupId.Properties["distinguishedName"][0].ToString();
                membersDnResult.Add(dn);
            }
        }

        return membersDnResult.ToArray();
    }

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