Разрешения UserPrincipal.FindByIdentity

Я пытаюсь использовать библиотеку .NET System.DirectoryServices.AccountManagement для получения UserPrincipal для определенного пользователя Active Directory.

У меня есть следующий код:

PrincipalContext context = new PrincipalContext(ContextType.Domain, "DomainName");
userPrincipal = UserPrincipal.FindByIdentity(context, IdentityType.SamAccountName, username);

Этот код работает как допустимый пользователь домена, но при его выполнении я получаю следующее исключение:

System.DirectoryServices.DirectoryServicesCOMException(0x8007052E): Ошибка входа в систему: неизвестное имя пользователя или неверный пароль.

Интересно, что я могу сделать следующий вызов, используя тот же контекст, без проблем:

context.ValidateCredentials(username, password, ContextOptions.Negotiate)

Идеи?

Ответы

Ответ 1

Вам нужно использовать конструктор PrincipalContext, который принимает имя пользователя и пароль.

Причина, по которой Validate работает, заключается в том, что она использует предоставленные учетные данные для привязки к каталогу.

Ответ 2

Похоже, что у вас есть сохраненные сетевые учетные данные. В Windows вы можете указать использование разных учетных данных сети при попытке достичь сетевых ресурсов. Я могу воспроизвести точно ту же проблему, что и вы, установив неверные сетевые учетные данные.

Предполагая, что ваш домен называется yourdomain.com, вы можете сказать, что Windows всегда будет использовать определенное имя пользователя и пароль всякий раз, когда он разговаривает с любыми компьютерами с достаточным количеством yourdomain.com.

=== Windows 7/2008 ===

  • Запустите "Crendentail Manager".
  • В разделе учетных данных Windows нажмите Add a Windows credentials
  • В сетевом адресе введите *.yourdomain.com
  • В имени пользователя и пароле введите неправильное имя пользователя или неверный пароль.

=== Windows XP/2000/2003 ===

  • Нажмите "Пуск" и "Выполнить"
  • Введите control keymgr.dll
  • Нажмите кнопку "Добавить" в диалоговом окне "Сохраненные имена пользователей и пароли"
  • В текстовом поле сервера введите *.yourdomain.com
  • В имени пользователя и пароле введите неправильное имя пользователя или неверный пароль.

Если это действительно проблема, с которой вы сталкиваетесь, легко устранить сохраненные пароли.

Почему работает context.ValidateCredentials(имя пользователя, пароль, ContextOptions.Negotiate)? Это просто потому, что вы инициализируете другую аутентификацию Kerberos/NTLM, так как вы снова предоставляете uername и password. Под капотом, если выбрана Kerberos, он отправит контроллеру домена предоставленное имя пользователя и пароль и обмене на билет Kerberos TGT. Затем ваша машина получит билет на услугу на сервере LDAP, используя этот билет TGT. Затем ваш аппарат отправит этот служебный билет на сервер LDAP. Обратите внимание, что этот билет обслуживания не будет сохранен в текущем сеансе входа в систему.

Почему UserPrincipal.FindByIdentity не работает? Если у вас нет сохраненного пароля, обычно он должен работать, потому что Windows будет использовать текущий билет пользователя TGT для входа в систему для обмена на билет службы сервера LDAP. Не существует процесса проверки имени пользователя и пароля. Однако, если у вас плохой пароль пользователя, Windows подумает, что он не должен использовать текущий билет пользователя TGT для входа в систему. Вместо этого он должен получить новый билет TGT, используя сохраненный сетевой пароль. Это причина, по которой вы видите System.DirectoryServices.DirectoryServicesCOMException (0x8007052E): Logon failure: unknown user name or bad password.