应用程序中的 DirectorySearcher 代码偶尔会返回不正确的结果,但在独立的测试应用程序中始终准确

问题描述 投票:0回答:1

我有一个在 Windows 服务下运行的 C# .NET 6 控制台应用程序,该应用程序使用

DirectorySearcher
来确定联系人(从 CRM 的 SQL 数据库读取)当前是否也存在于 Active Directory 中。即使多次重复完全相同的搜索,从
DirectorySearcher
返回的结果也不一致(本质上,搜索有时会找到联系人,有时找不到联系人,即使它存储在搜索的 OU 中)。

然后,我创建了一个作为计划任务运行的 C# .NET 6 控制台测试应用程序。它隔离故障应用程序中使用的完全相同的搜索代码,并对输入的搜索条件重复相同的搜索三次。该应用程序始终返回准确的搜索结果。 (由于 gMSA 提供的凭据以及需要输入电子邮件 ID 进行测试,测试应用程序是一项计划任务。)

这是出现故障的应用程序和正常运行的测试应用程序中使用的代码:

public (bool ContactExists, DirectoryEntry DirectoryEntryObjectNullIfFalse) ADContactExists(int srcId, long emailId, bool shortEmailIdNeedsConversion, bool searchExceptionsPath = false)
{
    #if STAGING || DEBUG
        string searchPath = configuration.GetValue<string>("ActiveDirectory:StagingAdsSearchPath");
    #else
        string searchPath = App_Configuration.GetAdsClientsPath();
    #endif

    if (searchExceptionsPath)
        searchPath = App_Configuration.GetAdsExceptionsPath();

    using (DirectoryEntry rootDirectoryEntry = App_Configuration.GetCredentialedDirectoryEntry(false, searchPath))
    {
        using (DirectorySearcher ds = new DirectorySearcher(rootDirectoryEntry))
        {
            ds.SearchScope = SearchScope.OneLevel;
            long longEmailId = 0;

            if (shortEmailIdNeedsConversion)
                longEmailId = InterActionShortIdConversions.ConvertToLongInterActionID(srcId, emailId);
            else
                longEmailId = emailId;

            ds.Filter = GetFilter("extensionAttribute8", "=", longEmailId.ToString());
            ds.PropertiesToLoad.Add("extensionAttribute8"); //InterAction Email ID (Converted Long Form)

            SearchResult sr = ds.FindOne();

            if (sr != null)
            {
                //Update existing Active Directory contact
                DirectoryEntry directoryEntryResult = App_Configuration.GetCredentialedDirectoryEntry(false, sr.Path);
                return (true, directoryEntryResult);
            }
            else
            {
                //Create new Active Directory contact
                DirectoryEntry directoryEntryResult = new DirectoryEntry();
                return (false, directoryEntryResult);
            }
        }
    }
}

public string GetFilter(string property, string comparisonOperator, string propertyValue)
{
    string filter = "(&(objectCategory=person)(objectClass=contact)(" + property + comparisonOperator + propertyValue + "))";
    return filter;
}
  • 我使用的是 7.01 版本
    System.DirectoryServices
  • 这似乎不是由于对域控制器的 LDAP 调用没有请求的信息而导致的问题,因为此问题发生在已在 Active Directory 中多年的联系人上。
  • 出现故障的解决方案是使用 Visual Studio 2022 中的发布解决方案配置进行编译的。我尝试了非发布编译,并观察到一些总是产生不正确搜索结果的联系人在不使用发布编译时产生了正确的搜索结果(尽管其他搜索结果仍然不正确)。编译似乎会影响这个问题,但我不知道为什么或如何。
  • 执行了 TDD 和 Wireshark 跟踪,但到目前为止还没有任何结果(数据仍在审查中)
  • 由于使用
    NServiceBus
    Quartz.NET
    ,故障应用程序具有一些异步 (async await) 代码,但大多数是同步的。话虽这么说,异步代码确实调用了一些同步方法,然后调用
    DirectorySearcher
    代码。如果有人认为异步代码可能以某种方式影响 Active Directory 搜索,我会提到这一点。

非常感谢您为

DirectorySearcher
持续返回准确结果提供的所有帮助。

c# active-directory ldap .net-6.0
1个回答
0
投票

该问题是由异步填充和读取 C#

Dictionary
引起的。由于某些线程会在完全填充之前访问
Dictionary
,因此有时会向 Active Directory 搜索提交不正确的信息(例如空值),从而导致检索到不正确的结果。

我尝试使用

ConcurrentDictionary
来纠正这个问题,如SO帖子在从读取字典内容的线程访问之前通过条件参数以异步方式填充C#字典中详细介绍的那样,但是这对于我的用例来说是不可能的,所以我最终重写了受影响方法的逻辑并完全删除
Dictionary
。一旦我这样做了,
DirectorySearcher
始终返回准确的结果。

© www.soinside.com 2019 - 2024. All rights reserved.