Active Directory: получить RootDSE в домене, находящемся в лесу с несколькими корнями?

У меня есть клиент, использующий службу Windows, которую я написал, которая опрашивает указанный сервер LDAP Active Directory для пользователей в указанных группах на этом сервере LDAP.

Как только он находит пользователя, он заполняет информацию о пользователе (например, имя пользователя, адрес электронной почты и т. Д.) И пытается получить домен пользователя на этом сервере LDAP.

Когда я пытаюсь получить домен пользователя для этого конкретного клиента, я получаю исключение DirectoryServicesCOMException: Ошибка входа в систему: неизвестное имя пользователя или неверный пароль. Это исключение возникает, когда я пытаюсь сослаться на свойство создаваемого мной объекта RootDSE DirectoryEntry.

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

Домены и доверие Active Directory

  • ktregression.com

  • ktregression.root

Я предполагаю, что проблема в этом. Есть ли способ обойти это? Есть ли способ по-прежнему получить имя netbios определенного объекта домена, не сталкиваясь с этим исключением?

Вот пример кода, указывающего на настройку тестового сервера AD, как описано ранее:

        string domainNameLdap = "dc=tempe,dc=ktregression,dc=com";

        DirectoryEntry RootDSE = new DirectoryEntry (@"LDAP://10.32.16.6/RootDSE");
        DirectoryEntry servers2 = new DirectoryEntry (@"LDAP://cn=Partitions," + RootDSE.Properties["configurationNamingContext"].Value ); //*****THIS IS WHERE THE EXCEPTION IS THROWN********

        //Iterate through the cross references collection in the Partitions container
        DirectorySearcher clsDS = new DirectorySearcher(servers2);
        clsDS.Filter = "(&(objectCategory=crossRef)(ncName=" + domainNameLdap + "))";
        clsDS.SearchScope = SearchScope.Subtree;
        clsDS.PropertiesToLoad.Add("nETBIOSName");

        List<string> bnames = new List<string>();

        foreach (SearchResult result in clsDS.FindAll() )
            bnames.Add(result.Properties["nETBIOSName"][0].ToString());

person ghost_mv    schedule 23.11.2010    source источник
comment
Удостоверились ли вы, что либо RootDSE.Properties["configurationNamingContext"].Value возвращает значение, которое на самом деле не является нулевым, либо соответствует номенклатуре LDAP LDAP://CN=Partitions,DC=ktregression,DC=com или тому подобное?   -  person Will Marcouiller    schedule 23.11.2010
comment
Вы видели образец кода, который я вам предоставил для ответа на другой аналогичный вопрос вчера?   -  person Will Marcouiller    schedule 23.11.2010
comment
@Will, да, я взглянул на это и попробовал. Я ответил на это еще одним вопросом. Я думаю, что на самом деле у меня две отдельные проблемы, поэтому я начал и эту. Проблема, при которой у меня есть экземпляр двух корней в одном лесу.   -  person ghost_mv    schedule 23.11.2010
comment
Что касается проверки того, что RootDSE.Properties [configurationNamingContext] .Value возвращает значение и не является нулевым, я не могу выполнить эту проверку, потому что во второй раз, когда я пытаюсь получить, имеет ли оно значение, выдается исключение.   -  person ghost_mv    schedule 23.11.2010
comment
@Micheal: Я понял вашу точку зрения. Объясните, пожалуйста, чётко, в чем заключается ваша цель, забыв про код и все остальное, просто скажите, что вам нужно сделать, чтобы я мог к чему-то решиться. Я много работал и продолжаю использовать Active Directory последние несколько недель. Я надеюсь, что смогу помочь вам в дальнейшем. В качестве второй мысли, учитывая, что у вас два разных корня, почему бы просто не создать два независимых экземпляра класса DirectoryEntry, который будет представлять каждый из ваших корней, и работать с ними?   -  person Will Marcouiller    schedule 23.11.2010
comment
@Micheal: Используете ли вы олицетворение для этой службы Windows? В случае, когда вы не используете олицетворение, как это, кажется, имеет место здесь, в вашем примере кода, текущий пользователь, вошедший в систему, должен иметь права для подключения к AD и запроса его. В противном случае, я думаю, следует использовать олицетворение, а затем убедитесь, что ваша учетная запись службы Windows правильно настроена на обоих корнях.   -  person Will Marcouiller    schedule 23.11.2010
comment
Нет, я не использую выдачу себя за другое лицо. Сама служба Windows - это тот, кто получает доступ к информации, у которой есть доступ. Эта служба Windows настроена для получения строки сервера LDAP из базы данных через вызов веб-службы. Он также извлекает имя пользователя / пароль. Он также получает список групп, из которых нужно получить пользователей. Затем он ищет эти группы в этом LDAP. Для каждой группы, для каждого пользователя в группе, он извлекает информацию о пользователе и отправляет эту информацию по сети обратно на другой сервер для хранения другого приложения. Это моя цель. Но мне нужен домен пользователя.   -  person ghost_mv    schedule 23.11.2010
comment
Учетная запись службы Windows может иметь права, но если вы не используете олицетворение, она по умолчанию будет использовать пользователя, который в настоящее время аутентифицирован, и использовать его вместо вашей учетной записи службы Windows. Возможно, вам стоит попробовать использовать учетные данные вашей службы Windows при создании экземпляров обоих классов DirectoryEntry.   -  person Will Marcouiller    schedule 23.11.2010
comment
Итак, даже если я использую имя пользователя и пароль пользователя с правами при создании экземпляров моих объектов DirectoryEntry, он использует текущего пользователя, вошедшего в систему?   -  person ghost_mv    schedule 23.11.2010
comment
Вы не используете имя пользователя и пароль в конструкторе класса DirectoryEntry в вашем примере кода, тогда это будет использовать текущего пользователя, вошедшего в систему. Использование олицетворения заставит AD пройти аутентификацию с указанным именем пользователя и паролем. Для этого вы должны передать их в параметрах конструктора.   -  person Will Marcouiller    schedule 23.11.2010
comment
Моя ошибка в этом образце кода. Я добавил пользователя NT с правами администратора к вызову конструктора DirectoryEntry с тем же результатом.   -  person ghost_mv    schedule 24.11.2010


Ответы (2)


Похоже, что учетная запись пользователя, с которой Active Directory пытается аутентифицировать «вас», не существует, как сообщает ваш DirectoryServicesCOMException.

DirectoryServicesCOMException: ошибка входа в систему: неизвестное имя пользователя или неверный пароль.

Посмотрите на свой образец кода, похоже, вы не используете олицетворение, поэтому протокол безопасности Active Directory принимает во внимание текущего аутентифицированного пользователя. Сделайте этого пользователя самостоятельно, тогда, если вы не определены в обоих корнях вашего домена, один из них не знает вас, что вызывает такого рода исключение.

С другой стороны, использование олицетворения может решить проблему здесь, поскольку вы говорите, что ваша учетная запись службы Windows имеет право запрашивать оба ваших корня в одном и том же лесу, тогда вы должны убедиться, что аутентифицированный пользователь является вашей службой Windows.

Ясно, что это означает, что без олицетворения вы не можете гарантировать, что аутентифицированный пользователь ЯВЛЯЕТСЯ вашей службой Windows. Чтобы убедиться в этом, необходимо обязательно использовать выдачу себя за другое лицо.

Теперь о двух корнях

  1. ktregression.com;
  2. ktregression.root.

Это два разных и независимых корня. Из-за этого, я думаю, вам следует использовать два экземпляра класса DirectoryEntry, подходящие по одному для каждого корня.

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

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

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

private string _dotComRootPath = "LDAP://ktregression.com";
private string _dotRootRootPath = "LDAP://ktregression.root";
private string _serviceAccountLogin = "MyWindowsServiceAccountLogin";
private string _serviceAccountPwd = "MyWindowsServiceAccountPassword";

public string GetUserDomain(string rootPath, string login) {
    string userDomain = null;

    using (DirectoryEntry root = new DirectoryEntry(rootPath, _serviceAccountLogin, _serviceAccountPwd)) 
        using (DirectorySearcher searcher = new DirectorySearcher()) {
            searcher.SearchRoot = root;
            searcher.SearchScope = SearchScope.Subtree;
            searcher.PropertiesToLoad.Add("nETBIOSName");
            searcher.Filter = string.Format("(&(objectClass=user)(sAMAccountName={0}))", login);

            SearchResult result = null;

            try {
                result = searcher.FindOne();

                if (result != null) 
                    userDomain = (string)result.GetDirectoryEntry()
                                    .Properties("nETBIOSName").Value;                                     
            } finally {
                dotComRoot.Dispose();
                dotRootRoot.Dispose();
                if (result != null) result.Dispose();
            }
        }            

    return userDomain;
}

И используя это:

string userDomain = (GetUserDomain(_dotComRoot, "searchedLogin") 
                        ?? GetUserDomain(_dotRootRoot, "searchedLogin")) 
                    ?? "Unknown user";

Ваше исключение генерируется только при второй DirectoryEntry инициализации, которая предполагает, что у вашего текущего пользователя по умолчанию нет учетной записи, определенной в этом корне.

ИЗМЕНИТЬ №1

См. Мой ответ на другой ваш вопрос, связанный с именем NetBIOS, ниже:
C # Active Directory: получить доменное имя пользователя?
где я предлагаю новое и, возможно, более простое решение вашей проблемы.

Дайте мне знать, если у вас возникнут дополнительные вопросы. знак равно

person Will Marcouiller    schedule 23.11.2010

Я считаю, что DirectoryEntry имеет свойства, которые нужно указать для учетной записи AD, которая может выполнять запросы или обновления LDAP, вы также можете делегировать этот контроль из своего родительского домена.

person dexter    schedule 23.11.2010