使用 DirectorySynchronization 时获取 Microsoft Active Directory 属性 "memberOf" 的正确方法

Correct way to get Microsoft Active Directory attribute "memberOf" when using DirectorySynchronization

我定期读取应用程序的活动目录以将当前状态存储在数据库中。 为了减少数据量,我使用 DirectorySynchronization 仅获取自上次查询以来的更改。 但是现在我还需要使用 DirectorySynchronization 时 DirectorySearcher 未提供的属性“memberOf”。

目前我得到了每个找到的条目的 DirectoryEntry,但是随后提供的属性比我需要的多,这与实际意图相矛盾。

有没有一种方法可以设置使用 DirectoryEntry 读取哪些属性,类似于使用 DirectorySearcher 的 PropertiesToLoad,或者有没有更好的方法来在使用 DirectorySynchronization 时读取属性“memberOf”?

代码摘录:

using System.DirectoryServices;

DirectoryEntry searchRoot = new DirectoryEntry(domain, username,password, AuthenticationTypes.Secure);
DirectorySearcher dirSearch = new DirectorySearcher(searchRoot);
dirSearch.PropertiesToLoad.Add("samaccountname");
dirSearch.PropertiesToLoad.Add("distinguishedname");
dirSearch.PropertiesToLoad.Add("mail");
//filter to user objects
dirSearch.Filter = "(objectCategory=person)";
dirSearch.Filter = "(objectClass=user)";

byte[] cookie = null;
DirectorySynchronization sync = new DirectorySynchronization(DirectorySynchronizationOptions.ObjectSecurity,cookie);
    
dirSearch.DirectorySynchronization = sync;
using (searchRoot)
{
    using (SearchResultCollection results = dirSearch.FindAll())
    {
        foreach (SearchResult result in results)
        {
            DirectoryEntry dirEntry = result.GetDirectoryEntry();
            List<string> memberOf = new List<string>();
            PropertyValueCollection prop = dirEntry.Properties["memberof"];
            
            foreach(var member in prop)
            {
                memberOf.Add((string)member);
            }
            
        }
    }
    cookie = sync.GetDirectorySynchronizationCookie();
}

But now I also need the attribute "memberOf" which is not provided by the DirectorySearcher when using DirectorySynchronization.

memberOf是目录计算出来的一个特殊属性,所以DirectorySynchronization没有提供(实际上用的是DirSync control)。唯一可以提供DirectorySynchronization的是目录真正的修改,属于用户DN添加到member属性中的group对象(哪种触发memberOf重新计算)

At the moment I get the DirectoryEntry for each found entry, but then more attributes are delivered than I need, which contradicts the actual intention.

GetDirectoryEntry 执行新的目录搜索并加载所有属性(它没有 link DirectorySearcher 设置和先前的搜索)。

因此,您可以使用另一个 DirectorySearcher(将只加载 memberOf),而不是 GetDirectoryEntry,它将在每个循环中执行一次搜索(示例没有任何强测试,即 null 值等):

using (searchRoot)
{
    using (SearchResultCollection results = dirSearch.FindAll())
    {
        // A new DirectorySearcher
        DirectorySearcher anotherDirectorySearcher = new DirectorySearcher(searchRoot);
        anotherDirectorySearcher.PropertiesToLoad.Add("memberOf");
        foreach (SearchResult result in results)
        {
            // A new filter on each loop in order to look for an single entry
            anotherDirectorySearcher.Filter = $"(samaccountname={(string)result.Properties["samaccountname"][0]})";
            List<string> memberOf = new List<string>();            
            foreach(var member in anotherDirectorySearcher.FindOne().Properties["memberOf"])
            {
                memberOf.Add((string)member);
            }
            
        }
    }
    cookie = sync.GetDirectorySynchronizationCookie();
}

注意:

dirSearch.Filter = "(objectCategory=person)";
// Here you override the previous one (the Filter property is a string)
dirSearch.Filter = "(objectClass=user)";
// If you want both, you can use:
dirSearch.Filter = "(&(objectCategory=person)(objectClass=user))";