Метод DirectoryEntry SetPassword возвращает исключение "Отказано в доступе"

В приложении asp.net MVC я сталкиваюсь с ошибкой " Отказано в доступе" при попытке сброса пароля с помощью directoryEntry.Invoke,

К странице обращается пользователь, пытающийся изменить свой пароль и SSL required а также Client Certificates - Required помечены в IIS.

Соответствующий код:

directoryEntry.Invoke("SetPassword", new object[] { model.Password });
                directoryEntry.Properties["LockOutTime"].Value = 0;
                directoryEntry.Close();

Точная ошибка -

System.Reflection.TargetInvocationException: Exception has been thrown by the target of an invocation. ---> System.UnauthorizedAccessException: Access is denied. (Exception from HRESULT: 0x80070005 (E_ACCESSDENIED))
   --- End of inner exception stack trace ---
   at System.DirectoryServices.DirectoryEntry.Invoke(String methodName, Object[] args)

Web.config -

<authentication mode="Windows" />
    <identity impersonate="false" />
    <authorization>
      <deny users="?" />
    </authorization>
  • Пул приложений работает под учетной записью AD; также является частью локальной группы администраторов [Domain1\AppPoolUser],
  • Приложение запрашивает сертификат пользователя
  • Пользователь пытается сменить пароль [Domain2\testUser] и учетная запись, под которой запущен пул приложений, находится в разных доменах, но это вряд ли проблема. Действующие разрешения для AppPoolUser позволяют ChangePassword для учетной записи testUser.
  • Я даже пытался запустить пул приложений под той же учетной записью, что и тестовая, но это ничего не меняет.

Проверил онлайн, но мне не ясно, в чем проблема. Самая близкая связанная вещь, которую я вижу, - это - Установка разрешений ASP.Net - Доступ запрещен. (Исключение из HRESULT: 0x80070005 (E_ACCESSDENIED))

Однако, как упоминалось в моем случае, пул приложений работает под ограниченной технической учетной записью, и я не думаю, что есть какие-либо проблемы с сертификатами SSL.

  1. Нужно ли запрашивать делегирование контроля для учетной записи пула приложений в AD?
  2. Или есть другая проблема, которая мне не хватает.

1 ответ

У нас было похожее требование изменить или сбросить пароль. Мы используем следующий фрагмент кода.

        /// <summary>
        /// Resets the user password.
        /// </summary>        
        public static void ResetUserPassword(string domain, string domainUsername, string domainPassword, string sAMAccountName, string newPassword,
            bool askToChangePassword, bool unlockAccount, bool passRespectDomainPolicy, bool superuser)
        {
            // Get root directory entry
            using (var entry = GetDirectoryEntry(domain, domainUsername, domainPassword, AuthenticationTypes.Secure))
            {
                var displayName = string.Empty;

                // Search for the user with the same sAMAccountName
                using (var searcher = new DirectorySearcher(entry))
                {
                    // Filter results by SAMAccountName
                    searcher.Filter = string.Format("(SAMAccountName={0})", sAMAccountName);

                    // Search and return only one result
                    var result = searcher.FindOne();

                    // Check if result is returned
                    if (result == null) throw new Exception("Could not find user: " + sAMAccountName);

                    // Get the user directory entry
                    var userEntry = result.GetDirectoryEntry();

                    // Read name value
                    if (userEntry.Properties.Contains("displayName") && userEntry.Properties["displayName"].Count > 0)
                        displayName = Convert.ToString(userEntry.Properties["displayName"][0]);

                    // Validate password
                   // string errorMessage;
                   // if (passRespectDomainPolicy &&
                     //   !IsValidPassword(domain, sAMAccountName, newPassword, displayName, userEntry, superuser, out errorMessage))
                    // {
                      //  if (!string.IsNullOrEmpty(errorMessage)) throw new Exception(errorMessage);
                      //  throw new Exception("Password is not valid as per AD policy. Please consult Administrator.");
                    // }

                    // Earlier we used impersonation to reset password on same DC.
                    // But that didn't worked and so removed.
                    userEntry.Invoke("SetPassword", newPassword);

                    // 0(for on) and -1(for off) for LDAP case. For WinNT it is opposite.
                    // Set "Ask to change password at next login"
                    if (askToChangePassword)
                        userEntry.Properties["pwdLastSet"].Value = 0;

                    // Unlock account if required
                    if (unlockAccount)
                        userEntry.Properties["lockoutTime"].Value = 0;

                    // Commit changes
                    userEntry.CommitChanges();
                }
            }
        }

Заметным моментом является то, что мы запускаем код userEntry.Invoke("SetPassword", newPassword); внутри контекста записи корневого каталога using (var entry = GetDirectoryEntry(domain, domainUsername, domainPassword, AuthenticationTypes.Secure)){,

я имею в виду, что entry представляет объект, содержащий имя пользователя и пароль администратора домена. Этот администратор должен иметь полное разрешение на внесение изменений в AD.

Дайте нам знать ваши результаты тестирования.

Другие вопросы по тегам