2010-08-26 3 views
15

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

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

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

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

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

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

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

Идеи?

+0

Проверьте этот ответ: http://stackoverflow.com/questions/1863801/findbyidentity-failing-with-pricipaloperationexception-in-asp-net-webapp/3515280#3515280 –

ответ

12

Необходимо использовать конструктор PrincipalContext, в котором принимают имя пользователя и пароль.

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

+0

Это не Мне очень нравится. Вы говорите, что вызов ValidateCredentials использует текущие учетные данные, но вызов UserPrincipal.FindByIdentity, который принимает этот контекст, не работает? Если это так, как мне заставить его использовать текущую идентификацию (как, например, идентификатор потока), чтобы позвонить? У меня нет имени пользователя или пароля для передачи, так как это приложение, запущенное как настройка учетной записи службы во время установки. Я не могу хранить эти учетные данные в любом месте. – RMD

+0

Я думаю, что вы неправильно поняли, ValidateCredentials использует учетные данные, предоставленные в списке параметров для ValidateCredentials. Контекст, который вы определили, не имеет учетных данных, связанных с ним, кроме тех, которые относятся к текущему потоку. Я подозреваю, что ваши проблемы связаны с конфигурацией/развертыванием сервера. Убедитесь, что учетная запись, выполняющая службу, была делегирована в пределах домена. – Nate

+0

Да, я неправильно понял. Пользователь текущего потока определенно является допустимым пользователем домена. Когда вы говорите «делегировано в пределах домена», что вы имеете в виду? – RMD

3

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

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

=== Окна 7/2008 ===

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

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

  1. Нажмите кнопку Пуск и Выполнить
  2. Введите control keymgr.dll
  3. Нажмите кнопку Добавить на «Сохранение имен пользователей и паролей» диалоговые
  4. В текстовом окне Сервер, положить в *.yourdomain.com
  5. В имя пользователя и пароль, поставить в неправильном имя пользователя или неправильный пароль

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

Почему работает 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.

+0

Интересно. Этот код работает из контекста приложения ASP.NET, поэтому я не думаю, что сохраненные пароли имели бы значение. Я проверю, правильно ли ты. – RMD

+0

@RMD Ах, вы пропустили эту информацию. Используете ли вы проверку подлинности Windows? Или вы просто используете локальную учетную запись службы для доступа к AD? –

+0

Как я уже сказал в своем оригинальном посте: «Этот код работает как действительный пользователь домена». – RMD