Как установить/изменить пароль пользователя Active Directory через домены с помощью С#.NET?
Я уже довольно давно искал, как устанавливать/изменять пароль и отзывать/восстанавливать пользователя, но еще не найти решение, которое действительно работает для меня.
Я начинаю склоняться к тому, что я пересекаю домены как проблему, хотя я могу программно создавать/удалять/обновлять и даже подключать/отключать пользователей от групп.
В основном, я пробовал следующие способы:
DirectoryEntry account = new DirectoryEntry("LDAP://" + adHostname + "/" + dn, adUserName, adPassword);
account.Invoke("SetPassword", "Password1");
account.Properties["LockOutTime"].Value = 0;
account.CommitChanges();
А также
account.Invoke("SetPassword", new object[] { "Password1" });
Оба они в конечном счете выдают ошибку "Один или несколько входных параметров недействительны \r\n"
Затем я попытался использовать подход .NET 3.5 с использованием основного контекста.
using (var context = new PrincipalContext(ContextType.Domain, adHostname, myContainer, ContextOptions.SimpleBind, adUserName, adPassword))
{
using (var user = UserPrincipal.FindByIdentity(context, account.Properties["sAMAccountName"].Value.ToString()))
{
user.SetPassword(password);
}
}
Этот подход также вызывает ту же ошибку, что и выше. Если я переключу некоторые вещи (я не могу вспомнить все комбинации, которые я пробовал), это иногда вызывает "Локальная ошибка" COM Exception.
Любая помощь очень ценится.
Ответы
Ответ 1
См. статью:
https://www.codeproject.com/Articles/18102/Howto-Almost-Everything-In-Active-Directory-via-C#7
Вы заметите, что во всех образцах мы привязываемся непосредственно к directoryEntry и не указываем сервер или учетные данные. Если вы не хотите использовать класс олицетворения, вы можете отправлять учетные данные непосредственно в конструктор DirectoryEntry. Класс олицетворения полезен для тех времен, когда вы хотите использовать статический метод и не хотите, чтобы возникли проблемы с созданием объекта DirectoryContext для хранения этих деталей. Аналогично, вы можете настроить таргетинг на определенный контроллер домена.
Специальные контроллеры домена или учетные данные
Везде в коде, который вы видите: LDAP://вы можете заменить LDAP://MyDomainControllerNameOrIpAddress, а также везде, где вы строите класс DirectoryEntry, вы можете отправлять также определенные учетные данные. Это особенно полезно, если вам нужно работать в Active Directory, для которого ваш компьютер не является его членом или доменом, или вы хотите настроить таргетинг на DC, чтобы внести изменения.
//Переименовать объект и указать контроллер домена и учетные данные напрямую
public static void Rename(string server,
string userName, string password, string objectDn, string newName)
{
DirectoryEntry child = new DirectoryEntry("LDAP://" + server + "/" +
objectDn, userName, password);
child.Rename("CN=" + newName);
}
Ответ 2
"new DirectoryEntry" не привязывает учетную запись пользователя. Пользователю необходимо найти пароль для установки пароля. Вот так:
DirectoryEntry account = new DirectoryEntry("LDAP://" + adHostname + "/" + dn, null, null, AuthenticationTypes.Secure | AuthenticationTypes.Sealing | AuthenticationTypes.Signing);
DirectorySearcher search = new DirectorySearcher(account);
search.Filter = "(&(objectClass=user)(sAMAccountName=" + adUserName + "))";
account = search.FindOne().GetDirectoryEntry();
account.Invoke("SetPassword", "Password1");
account.Properties["LockOutTime"].Value = 0;
account.CommitChanges();
Ответ 3
Этот всегда работает для меня. Надеюсь, поможет.
Сначала добавьте ссылку на System.DirectoryServices.AccountManagement
string hostName = "myDomain";
string adminName = "admin";
string adminPassword = "password";
public static void ResetPassword(string username, string password)
{
using (PrincipalContext pContext = new PrincipalContext(ContextType.Domain, hostName, adminName, adminPassword))
{
UserPrincipal up = UserPrincipal.FindByIdentity(pContext, username);
if (up != null)
{
up.SetPassword(password);
up.Save();
}
}
}
Вы также можете делать все возможное для UserPrincipal, например, для учетной записи блокировки, истечения срока действия пароля, получения последнего входа и т.д.