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

В моем приложении MVC-5 я добавляю/редактирую пользователей в активном каталоге через свое приложение. Всякий раз, когда я вношу изменения в AD, каждый раз мне нужно передать ldapUserName(Admin) и ldapPassword(pass@123) для подключения к Active Directory. Тогда только я могу выполнять работу в AD. Вместо передачи учетных данных каждый раз, когда я хотел бы использовать учетную запись службы (domain\service_account), под которой мое приложение работает для подключения к AD. Как этого добиться??


person Kapil Kumar    schedule 17.10.2016    source источник
comment
Заранее спасибо !   -  person Kapil Kumar    schedule 17.10.2016
comment
как подключиться к АД   -  person lordkain    schedule 17.10.2016
comment
Вы пытались установить учетную запись пула приложений в качестве учетной записи администратора AD? Возможно, вам потребуется предоставить разрешения на добавление папок для этой учетной записи, чтобы получить доступ к папкам сайта.   -  person Stinky Towel    schedule 17.10.2016
comment
попробуйте { использование (var directoryEntry = new DirectoryEntry (ldabPath, ldapUserName, ldapPassword)) { использование (var newUser = directoryEntry.Children.Add (CN = + userViewModel.UserName, User)) { newUser.CommitChanges(); newUser.Invoke (setpassword, userViewModel.Password); newUser.Properties[userAccountControl].Value = 0x0200; новыйПользователь.СовершитьИзменения(); } }   -  person Kapil Kumar    schedule 17.10.2016
comment
приведенный выше код используется для добавления пользователя в AD. Вместо передачи учетных данных я хочу использовать учетную запись службы. Мне нужен беспрепятственный доступ к AD с использованием сервисной учетной записи.   -  person Kapil Kumar    schedule 17.10.2016
comment
Проверьте это также: stackoverflow.com/a/37565248/2779990   -  person Stinky Towel    schedule 17.10.2016
comment
Я проверил это, но не смог найти свой ответ. Без использования учетных данных, как вы можете подключиться к AD.   -  person Kapil Kumar    schedule 18.10.2016


Ответы (2)


Простое создание DirectoryEntry с помощью new DirectoryEntry(ldabPath, null, null) будет использовать учетные данные текущего пользователя (учетная запись службы в случае службы Windows). Ключ передает null как имя пользователя, так и пароль.

Это то, что вы хотите?

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

person baldpate    schedule 18.10.2016

Вы можете выбрать один из 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 одноэлементным.

person oldovets    schedule 17.10.2016
comment
Можете ли вы объяснить в деталях? - person Kapil Kumar; 18.10.2016
comment
@Kapil Kumar: создал подробный ответ, пожалуйста - person oldovets; 19.10.2016