В моем приложении MVC-5 я добавляю/редактирую пользователей в активном каталоге через свое приложение. Всякий раз, когда я вношу изменения в AD, каждый раз мне нужно передать ldapUserName(Admin) и ldapPassword(pass@123) для подключения к Active Directory. Тогда только я могу выполнять работу в AD. Вместо передачи учетных данных каждый раз, когда я хотел бы использовать учетную запись службы (domain\service_account), под которой мое приложение работает для подключения к AD. Как этого добиться??
Хотите использовать учетную запись службы для подключения к AD, под которой работает мое приложение
Ответы (2)
Простое создание DirectoryEntry
с помощью new DirectoryEntry(ldabPath, null, null)
будет использовать учетные данные текущего пользователя (учетная запись службы в случае службы Windows). Ключ передает null как имя пользователя, так и пароль.
Это то, что вы хотите?
Просто убедитесь, что учетная запись службы имеет достаточно прав для установки пароля для всех вовлеченных пользователей.
Вы можете выбрать один из 2-х вариантов.
Вариант 1. Вы запускаете свое приложение на компьютере, который присоединен к домену, откуда вы добавляете\удаляете пользователей. В этом случае самым простым решением является запуск вашего приложения (пула приложений) под учетной записью домена с достаточными разрешениями (простым способом может быть учетная запись, принадлежащая группе администраторов домена. Будет также администратором на хосте, где работает приложение)
Вариант 2. Вы запускаете свое приложение на отдельном компьютере, не присоединенном к домену. В этом случае вы можете выбрать один из следующих вариантов:
А. Выдайте себя за свой поток, чтобы действовать как учетная запись домена при выполнении всех сетевых подключений. Вам необходимо использовать LogonUser с флагом LOGON32_LOGON_NEW_CREDENTIALS. Недостатком этого метода является то, что все сетевые подключения (например, вы подключаетесь к сетевому ресурсу) будут выполняться под учетной записью домена. Дополнительные сведения о реализации см. в этом сообщении.
B. Создайте диспетчер соединений, который создаст для вас DirectoryEntry с необходимыми учетными данными. См. код ниже:
public interface IDirectoryEntryManager
{
DirectoryEntry GetDirectoryEntry(string domain, string baseDn);
}
public interface ICredentialProvider
{
Credential GetCredential(string domain);
}
public class Credential
{
public string UserName { get; set; }
public string Password { get; set; }
}
public class DirectoryEntryManager : IDirectoryEntryManager, IDisposable
{
private class DomainConnectionInfo
{
internal DomainConnectionInfo(string server, Credential credential)
{
Server = server;
Credential = credential;
}
internal string Server { get; private set; }
internal Credential Credential { get; private set; }
}
private bool disposed;
ICredentialProvider _credentialProvider;
Dictionary<string, DomainConnectionInfo> connectionsInfo = new Dictionary<string, DomainConnectionInfo>(StringComparer.OrdinalIgnoreCase);
Dictionary<string, DirectoryEntry> connections = new Dictionary<string, DirectoryEntry>(StringComparer.OrdinalIgnoreCase);
public DirectoryEntryManager(ICredentialProvider credentialProvider)
{
_credentialProvider = credentialProvider;
}
public DirectoryEntry GetDirectoryEntry(string domain, string baseDn)
{
if (disposed)
{
throw new ObjectDisposedException(this.GetType().Name);
}
return GetOrCreateConnection(domain, baseDn);
}
public void Dispose()
{
if (!disposed)
{
foreach (var connection in connections)
{
connection.Value.Dispose();
}
connections.Clear();
disposed = true;
}
}
private DirectoryEntry GetOrCreateConnection(string domain, string baseDn)
{
DomainConnectionInfo info;
if (!connectionsInfo.TryGetValue(domain, out info))
{
var credential = _credentialProvider.GetCredential(domain);
var dc = DomainController.FindOne(new DirectoryContext(DirectoryContextType.Domain, credential.UserName, credential.Password));
info = new DomainConnectionInfo(dc.Name, credential);
// maintaining a connection to rootDse object to make all LDAP queries use this single connection under the hood. Increasing performance
var entry = new DirectoryEntry(string.Format("LDAP://{0}/RootDSE", dc.Name));
entry.RefreshCache();
connections.Add(domain, entry);
connectionsInfo.Add(domain, info);
}
return new DirectoryEntry(string.Format("LDAP://{0}/{1}", info.Server, baseDn), info.Credential.UserName, info.Credential.Password);
}
}
Код не тестировал. Использовать привязку к серверу вместо привязки без сервера (например, LDAP://domain.com) лучше в случае, если вы создаете пользователя в одной части программы и пытаетесь получить к нему доступ в другой части. Используя бессерверную привязку, вы можете подключаться к разным контроллерам домена, поэтому пользователь, к которому вы пытаетесь получить доступ, может не быть реплицирован на второй контроллер домена.
Имейте в виду, что контроллер домена может стать недоступным, поэтому вам необходимо реализовать логику для поиска другого контроллера домена и при необходимости обновить кэш подключений.
Вы можете хранить учетные данные в файле\LSA, возможно, зашифрованном, и сделать класс DirectoryEntryManager одноэлементным.