Nano Hash - криптовалюты, майнинг, программирование

Ошибка .NET 4.5 в UserPrincipal.FindByIdentity (System.DirectoryServices.AccountManagement)

При тестировании нашего приложения .NET 4.0 под .NET 4.5 мы обнаружили проблему с FindByIdentity методом для UserPrincipal. Следующий код работает при запуске в среде выполнения .NET 4.0, но не работает в среде .NET 4.5:

[Test]
public void TestIsAccountLockedOut()
{
    const string activeDirectoryServer = "MyActiveDirectoryServer";
    const string activeDirectoryLogin = "MyADAccount@MyDomain";
    const string activeDirectoryPassword = "MyADAccountPassword";
    const string userAccountToTest = "TestUser@MyDomain";
    const string userPasswordToTest = "WRONGPASSWORD";

    var principalContext = new PrincipalContext(ContextType.Domain, activeDirectoryServer, activeDirectoryLogin, activeDirectoryPassword);

    var isAccountLockedOut = false;
    var isAuthenticated = principalContext.ValidateCredentials(userAccountToTest, userPasswordToTest, principalContext.Options);
    if (!isAuthenticated)
    {
        // System.DirectoryServices.AccountManagement.PrincipalOperationException : Information about the domain could not be retrieved (1355).
        using (var user = UserPrincipal.FindByIdentity(principalContext, IdentityType.UserPrincipalName, userAccountToTest))
        {
            isAccountLockedOut = (user != null) && user.IsAccountLockedOut();
        }
    }
    Assert.False(isAuthenticated);
    Assert.False(isAccountLockedOut);
}

Вот трассировка стека исключений:

System.DirectoryServices.AccountManagement.PrincipalOperationException : Information about the domain could not be retrieved (1355).
at System.DirectoryServices.AccountManagement.Utils.GetDcName(String computerName, String domainName, String siteName, Int32 flags)   at System.DirectoryServices.AccountManagement.ADStoreCtx.LoadDomainInfo()   at 
System.DirectoryServices.AccountManagement.ADStoreCtx.get_DnsDomainName()   at System.DirectoryServices.AccountManagement.ADStoreCtx.GetAsPrincipal(Object storeObject, Object discriminant)   at 
System.DirectoryServices.AccountManagement.ADStoreCtx.FindPrincipalByIdentRefHelper(Type principalType, String urnScheme, String urnValue, DateTime referenceDate, Boolean useSidHistory)   at 
System.DirectoryServices.AccountManagement.ADStoreCtx.FindPrincipalByIdentRef(Type principalType, String urnScheme, String urnValue, DateTime referenceDate)   at 
System.DirectoryServices.AccountManagement.Principal.FindByIdentityWithTypeHelper(PrincipalContext context, Type principalType, Nullable`1 identityType, String identityValue, DateTime refDate)   at 
System.DirectoryServices.AccountManagement.Principal.FindByIdentityWithType(PrincipalContext context, Type principalType, IdentityType identityType, String identityValue)   at 
System.DirectoryServices.AccountManagement.UserPrincipal.FindByIdentity(PrincipalContext context, IdentityType identityType, String identityValue)   

Кто-нибудь еще видел и решил эту проблему? Если нет, есть ли лучший способ проверить IsAccountLockedOut статус учетной записи Active Directory?

Для справки, все наши тестовые машины находятся в одной подсети. Существуют отдельные серверы ActiveDirectory под управлением Windows Server 2003, 2008 и 2012 в различных функциональных режимах домена (см. Ниже). Код работает на машинах с .NET 4.0, но не работает на машинах с .NET 4.5.

Мы запускали код на трех машинах .NET:
- Windows 7 с .NET 4.0
- Windows Vista с .NET 4.5
- Windows Server 2012 с .NET 4.5

Мы опробовали следующие серверы Active Directory:
- Windows 2003 с функциональным режимом домена AD, установленным на собственный Windows 2000
- Windows 2003 с функциональным режимом домена AD, установленным на Windows Server 2003
- Windows 2008 с AD Функциональный режим домена установлен на собственный Windows 2000
- Windows 2008 с функциональным режимом домена AD установлен на Windows Server 2003
- Windows 2008 с функциональным режимом домена AD установлен на Windows Server 2008
- Windows 2012 с функциональным режимом домена AD Установлен режим Windows 2012

Все эти серверы Active Directory настроены как простой единый лес, а клиентские машины не являются частью домена. Они не используются ни для каких других функций, кроме проверки этого поведения, и не используют ничего, кроме Active Directory.


РЕДАКТИРОВАТЬ - 9 октября 2012 г.

Спасибо всем, кто ответил. Ниже показан клиент командной строки C #, демонстрирующий проблему, и найденный нами краткосрочный обходной путь, который не потребовал от нас никаких изменений в конфигурациях Active Directory и DNS. Похоже, что исключение вызывается только один раз с экземпляром PrincipalContext. Мы включили выходные данные для машины .NET 4.0 (Windows 7) и машины .NET 4.5 (Windows Vista).

using System;
using System.DirectoryServices.AccountManagement;

namespace ADBug
{
    class Program
    {
        static void Main(string[] args)
        {
            const string activeDirectoryServer = "MyActiveDirectoryServer";
            const string activeDirectoryLogin = "MyADAccount";
            const string activeDirectoryPassword = "MyADAccountPassword";
            const string validUserAccount = "[email protected]";
            const string unknownUserAccount = "[email protected]";

            var principalContext = new PrincipalContext(ContextType.Domain, activeDirectoryServer, activeDirectoryLogin, activeDirectoryPassword);

            // .NET 4.0 - First attempt with a valid account finds the user
            // .NET 4.5 - First attempt with a valid account fails with a PrincipalOperationException
            TestFindByIdentity(principalContext, validUserAccount, "Valid Account - First Attempt");
            // Second attempt with a valid account finds the user
            TestFindByIdentity(principalContext, validUserAccount, "Valid Account - Second Attempt");
            // First attempt with an unknown account does not find the user
            TestFindByIdentity(principalContext, unknownUserAccount, "Unknown Account - First Attempt");
            // Second attempt with an unknown account does not find the user (testing false positive)
            TestFindByIdentity(principalContext, unknownUserAccount, "Unknown Account - Second Attempt");
            // Subsequent attempt with a valid account still finds the user
            TestFindByIdentity(principalContext, validUserAccount, "Valid Account - Third Attempt");
        }

        private static void TestFindByIdentity(PrincipalContext principalContext, string userAccountToTest, string message)
        {
            var exceptionThrown = false;
            var userFound = false;
            try
            {
                using (var user = UserPrincipal.FindByIdentity(principalContext, IdentityType.UserPrincipalName, userAccountToTest))
                {
                    userFound = (user != null);
                }
            }
            catch (PrincipalOperationException)
            {
                exceptionThrown = true;
            }
            Console.Out.WriteLine(message + " - Exception Thrown  = {0}", exceptionThrown);
            Console.Out.WriteLine(message + " - User Found = {1}", userAccountToTest, userFound);
        }
    }
}

Вывод .NET 4.0

Valid Account - First Attempt - Exception Thrown  = False
Valid Account - First Attempt - User Found = True
Valid Account - Second Attempt - Exception Thrown  = False
Valid Account - Second Attempt - User Found = True
Unknown Account - First Attempt - Exception Thrown  = False
Unknown Account - First Attempt - User Found = False
Unknown Account - Second Attempt - Exception Thrown  = False
Unknown Account - Second Attempt - User Found = False
Valid Account - Third Attempt - Exception Thrown  = False
Valid Account - Third Attempt - User Found = True

Вывод .NET 4.5

Valid Account - First Attempt - Exception Thrown  = True
Valid Account - First Attempt - User Found = False
Valid Account - Second Attempt - Exception Thrown  = False
Valid Account - Second Attempt - User Found = True
Unknown Account - First Attempt - Exception Thrown  = False
Unknown Account - First Attempt - User Found = False
Unknown Account - Second Attempt - Exception Thrown  = False
Unknown Account - Second Attempt - User Found = False
Valid Account - Third Attempt - Exception Thrown  = False
Valid Account - Third Attempt - User Found = True

  • Не уверен, что вы уже искали это в Google, но я нашел сообщение с несколькими комментариями об исправлениях для различных сценариев, которые могут вызвать это: elegancecode.com/2009/03/21/ Сам никогда не видел, но в интересах будучи полезным, я подумал, что поделюсь этим, так как это ВЫГЛЯДИТ полезно для меня. 26.09.2012
  • например, пробовали ли вы передать в DC и CN, например, PrincipalContext ctx = new PrincipalContext (ContextType.Domain, fabrikam.com, CN = Users, DC = fabrikam, DC = com, administrator, securelyStoredPassword); 26.09.2012
  • DJ, мы просто попробовали передать строку CN и DC, но она все еще работает под .NET 4.0 и не работает под .NET 4.5. 27.09.2012
  • Дэвид, я не думаю, что есть проблема с установкой, поскольку он работает под .NET 4.0. Мы добавили дополнительную справочную информацию о наших тестовых средах к исходному описанию. Спасибо. 27.09.2012
  • Просто хотел подтвердить, что эта проблема не только у вас. У меня есть почти идентичный фрагмент кода, который выдает такое же исключение в FindByIdentity. Я запускал его на трех компьютерах с одинаковыми сетевыми настройками, и только один с .NET 4.5 дает сбой. Я не спешу объявлять ошибки внешними, но до обновления это работало. 28.09.2012
  • Я отправил эту проблему группе разработчиков продукта в Microsoft. Кто-нибудь свяжется с вами в начале следующей недели. 30.09.2012
  • Не могли бы вы предоставить информацию об ОС для контроллера домена, машины, на которой произошел сбой? Команда разработчиков не смогла воспроизвести проблему с информацией в сообщении. Также небольшая информация о домене и строка сервера, которую вы передаете в конструкторе PrincipalContext 03.10.2012
  • @Anand - исходный пост был дополнен подробной информацией о протестированных конфигурациях клиента и сервера. Вот строки, которые мы используем для наших тестов: const string activeDirectoryServer = "vad2008"; const string activeDirectoryLogin = "[email protected]"; const string activeDirectoryPassword = "ADtest123"; const string userAccountToTest = "[email protected]"; const string userPasswordToTest = "WRONGPASSWORD"; 03.10.2012
  • Есть ли какой-либо общедоступный сервер ActiveDirectory, на котором мы могли бы проводить тесты, чтобы исключить возможность того, что это проблема конфигурации с нашей стороны? 04.10.2012
  • Как бы то ни было, ваш код отлично работал на моей машине, скомпилированной под .NET 4.5. Является ли [email protected] администратором домена? 05.10.2012
  • @CodeGrue Спасибо. Учетная запись, которую мы используем для создания PrincipalContext ([email protected]), является обычным пользователем без специальных разрешений. Является ли ваш клиентский компьютер членом домена? У нас нет, поэтому мы не полагаемся на какие-либо дополнительные разрешения, которые могут быть получены в результате этого. Может быть, поэтому ваш работает? 06.10.2012
  • Я тоже подтверждаю эту проблему. использование моментальных снимков d vmware для отказов системы до / после установки .net 4.5, чтобы убедиться, что это было при запуске проблемы. Мы также запрашиваем с машин, которые не находятся в запрашиваемом домене. Простая установка .net 4.5 приводит к тому, что рабочий код перестает работать с таргетингом на .net 4 или 4.5. Мы используем vs2010 с таргетингом на .net 4.0. измените цель на 3.5, и код работает даже после установки 4.5. 06.10.2012
  • и просто добавим - наши контроллеры домена - это win2k8r2 на функциональном уровне win2k8 r2, наши вызывающие клиенты также являются машинами win2k8r2. 06.10.2012
  • @Anand Еще одна информация. Используя контроллер домена Windows 2012 Active Directory на функциональном уровне win2012 и клиент Windows 7, было сделано следующее. .NET 4.0 на клиенте - ›тест пройден. Обновление до .NET 4.5 - ›тест не пройден. Изменен клиент, чтобы использовать сервер AD в качестве DNS-сервера. ›Тест пройден. Это верно, даже если мы используем IP-адрес вместо имени сервера для подключения в основном контексте. 08.10.2012
  • @Anand Другой тестовый пример: мы создали простой тестовый клиент командной строки, и когда мы запустили его на самом сервере Active Directory 2012 (под .NET 4.5), он работал нормально. Итак, мы продолжаем подозревать, что это как-то связано с конфигурацией серверов домена и клиентов. 09.10.2012
  • @GrandAvenueSoftware Спасибо за эти детали. Это поможет воспроизвести проблему локально. 09.10.2012
  • Я из .NET Framework - команда CLR. Мы не можем воспроизвести проблему на нашем внутреннем компьютере. Вероятно, это связано с чем-то, чего нет в нашей внутренней среде. Если у кого-нибудь есть репродукция под рукой, вы бы позволили нам отладить на вашей машине? Пожалуйста, напишите нам по адресу netfx45compat в Microsoft dot com для координации. После просмотра репродукции мы опубликуем результаты в этом посте. Заранее спасибо! - Варун, Совместимость с Microsoft .NET Framework. 15.10.2012

Ответы:


1

Для OP (и всех, кто помогал с ответами) у нас (была) такая же проблема. В нашей среде разработки установлен VS2012, и наше приложение сломалось во время выполнения во время входа в систему (проблема с AD, как указано выше). Так что я протер мою систему и продолжал использовать 2010, все время проливая слезу каждый раз, когда я читал новую запись в блоге о том, как хорош 2012 год, бла-бла.

Я нашел эту ветку благодаря Скотту Хансельману. Я установил виртуальную машину на свой ящик для разработки, на нее был установлен 90-дневный предварительный просмотр для разработчиков Windows 8 и VS2012. Наше приложение было запущено, и мы сразу же столкнулись с ошибкой входа в систему AD. Просто обернули наш FindByIdentity в try catch и заставили его повторить попытку после первого улова - и альт, он работает !! Так что спасибо тому, кто придумал этот маленький трюк !!

Итак, это незначительное исправление и «хак», который работает для локальной разработки и не должен влиять на производственную среду, поскольку в ближайшее время мы не будем запускать производственную версию 4.5.

Но недостатком является то, что локально вход в систему теперь занимает примерно 2 минуты по сравнению с секундами, когда мы работали под 2010 :(

Я действительно не знаю, что еще я могу предоставить, чтобы на самом деле попытаться помочь разрешить ситуацию, но решил, что я все равно поделюсь своими 2 центами, поскольку это все еще кажется серьезной проблемой.

09.11.2012
  • Спасибо за ответ. Мы подтвердили такое же поведение (первая попытка не удалась, все последующие успешны) и разместили тестовый клиент выше. Последний отзыв, который мы получили от Microsoft, был следующим: SDS.AM в .Net4.5 добавил ограничение, требующее разрешения доменного DNS на стороне клиента. Это было разработано с учетом того, что в соответствии с рекомендациями DNS должна быть правильная запись DNS. Основываясь на отзывах с форума, мы рассматриваем возможность снятия ограничения в следующем выпуске. 10.11.2012
  • Спасибо! Одна вещь, которую я также заметил, - это то, что после добавления ошибки при первой попытке - также есть значительная задержка при любых вызовах AD - разговоры 3 минуты +. Есть ли записи о моих локальных хостах, которые я могу добавить, чтобы решить эту проблему? Еще раз спасибо за отзыв! 12.11.2012
  • Я не уверен, связано ли это, но у нас всегда были значительные проблемы с производительностью при использовании имен хостов (например, myserver) вместо IP-адресов (например, 192.168.14.3) для сервера. Мы не проводили тестирования производительности обходного пути try-catch для этой проблемы, но я соберу тестовый пример и посмотрю, какие числа мы получим. 13.11.2012
  • Хороший!! попытка поймать вызов FindByIdentity () дважды сработала! -Спасибо 05.02.2013

  • 2

    У нас возникла точно такая же проблема (сбой междоменных запросов при обновлении до версии 4.5) - я бы счел это ошибкой, поскольку она нарушает существующий код (4.0).

    Однако, чтобы заставить его работать - взглянув на один из (теперь) отказавших клиентов, я заметил, что была куча DNS-запросов для записей SRV, которые не работали, в форме:

    _ldap._tcp.MYSERVER1.mydomain.com,INet,Srv
    _ldap._tcp.dc._msdcs.mydomain.com,INet,Srv
    

    Изменение нашего DNS-сервера (DNS, используемого отказавшими клиентами) для создания зоны пересылки для всего трафика mydomain.com к одному из контроллеров домена в домене решило проблему.

    При использовании nslookup поведение от предыдущего (когда он давал сбой) до настоящего (рабочего) состояло в том, что до того, как эти запросы возвращали «Несуществующий домен», теперь они возвращают «* Нет местоположения службы (SRV). записи доступны для ... ". Точка отказа, по-видимому, заключается в восприятии несуществования домена, а не в отсутствии записей SRV. Надеюсь, MS вернет это поведение, но тем временем вам может повезти с созданием зоны пересылки DNS, если вы можете контролировать DNS для отказавших клиентов.

    08.10.2012

    3

    У меня была такая же проблема после обновления .net framework с 4.0 до 4.5, я обновил структуру до .net 4.5.1, и это сработало.

    14.03.2017
  • У меня аналогичная проблема с методом IsMemberOf(). Моя версия .net - 4.5.2, но DNS кажется жестким требованием, которое мои тестовые машины не смогли выполнить. Любой обходной путь? 09.09.2018
  • Я начал новую тему здесь stackoverflow.com/questions/52242019/ 09.09.2018
  • Новые материалы

    Кластеризация: более глубокий взгляд
    Кластеризация — это метод обучения без учителя, в котором мы пытаемся найти группы в наборе данных на основе некоторых известных или неизвестных свойств, которые могут существовать. Независимо от..

    Как написать эффективное резюме
    Предложения по дизайну и макету, чтобы представить себя профессионально Вам не позвонили на собеседование после того, как вы несколько раз подали заявку на работу своей мечты? У вас может..

    Частный метод Python: улучшение инкапсуляции и безопасности
    Введение Python — универсальный и мощный язык программирования, известный своей простотой и удобством использования. Одной из ключевых особенностей, отличающих Python от других языков, является..

    Как я автоматизирую тестирование с помощью Jest
    Шутка для победы, когда дело касается автоматизации тестирования Одной очень важной частью разработки программного обеспечения является автоматизация тестирования, поскольку она создает..

    Работа с векторными символическими архитектурами, часть 4 (искусственный интеллект)
    Hyperseed: неконтролируемое обучение с векторными символическими архитектурами (arXiv) Автор: Евгений Осипов , Сачин Кахавала , Диланта Хапутантри , Тимал Кемпития , Дасвин Де Сильва ,..

    Понимание расстояния Вассерштейна: мощная метрика в машинном обучении
    В обширной области машинного обучения часто возникает необходимость сравнивать и измерять различия между распределениями вероятностей. Традиционные метрики расстояния, такие как евклидово..

    Обеспечение масштабируемости LLM: облачный анализ с помощью AWS Fargate и Copilot
    В динамичной области искусственного интеллекта все большее распространение получают модели больших языков (LLM). Они жизненно важны для различных приложений, таких как интеллектуальные..