|
||||||||||||||||||||||||||||||||||||
|
Глава 15Работа с активным каталогом Мы получаем активный каталог (Active Directory) как часть Windows 2000 Server. Активный каталог является службой каталога, где может храниться информация о пользователях, принтерах, службах и обычные данные. Exchange Server 2000 компании Microsoft интенсивно использует его для хранения общедоступных папок и другой информации. Мы также можем хранить в активном каталоге определяемые нами данные. В файловой системе каталог хранит файлы, телефонный каталог хранит телефонные номера и имена. Служба каталога делает доступной информацию в каталоге. С помощью Проводника можно, например, находить файлы. До появления ADS сервер Exchange мог использовать активный каталог для хранения своих объектов. Системным администраторам приходилось конфигурировать два идентификатора пользователя для одного человека: учетную запись пользователя в домене Windows NT, чтобы можно было зарегистрироваться в системе, и пользователя в Exchange Directory. Это было необходимо, так как для пользователей требовалась дополнительная информация (такая как адреса e-mail, телефонные номера и так далее), а данные о пользователях домена NT были нерасширяемыми, что не позволяло поместить туда требуемую информацию. Теперь системному администратору достаточно сконфигурировать только одного пользователя для человека в активном каталоге, данные объекта пользователя можно расширять, чтобы удовлетворить требованиям Exchange Server. Мы можем также расширить эту информацию. Рассмотрим менеджера проекта в большой компании, который ищет с помощью Active Directory разработчика, способного создать приложения с помощью C#. Было бы неплохо, если бы менеджер мог сделать простой запрос для получения списка всех разработчиков, удовлетворяющих его требованиям. Такую возможность предоставляет активный каталог, в котором объект пользователя дополняется списком навыков. Рассмотрим другой пример, где активный каталог может сыграть полезную роль: допустим, сконфигурирован используемый по умолчанию черно-белый принтер, но потребовалась цветная печать. Пользователь знает, что в пределах досягаемости имеется цветной принтер, который удовлетворяет требованиям, но какое у этого принтера имя? В диалоговом окне печати принтер можно выбирать из списка сотен странных имен типа Pikachu, Poliwag, Cloyster, Jynx, Staryu, которые когда-то выбрал системный администратор. Как выбрать правильный принтер? Давайте создадим решение, где пользователь может ввести такие требования, как расположение, двусторонняя печать и цвет для поиска принтера. Такая дополнительная информация о принтере также хранится в активном каталоге. С помощью среды .NET можно легко получить доступ и манипулировать данными в службе каталога с помощью классов из пространства имен System.DirectoryServices.
В этой главе мы рассмотрим: □ Архитектуру активного каталога. □ Чтение и изменение данных в активном каталоге. □ Поиск объектов в активном каталоге. Архитектура активного каталогаЗдесь мы рассмотрим, как работает активный каталог, для чего он используется и какие данные можно в нем хранить. СвойстваСвойства активного каталога представлены в следующем списке: □ Данные в активном каталоге группируются иерархически. Объекты могут храниться внутри других объектов-контейнеров. Вместо того чтобы входить в один большой список, пользователи могут группироваться внутри организационных единиц. Организационная единица включает в себя другие организационные единицы, и таким образом можно построить дерево. □ Активный каталог использует репликацию мультимастера. В противоположность доменам Windows NT 4, где контроллер первичного домена был мастером, при использовании активного каталога все серверы являются мастерами. Если первичный контроллер домена в домене Windows NT 4 выключен, ни один пользователь не может сменить пароль; системный администратор обновляет список пользователей только в том случае, когда первичный контроллер домена включен и работает. При использовании активного каталога обновление можно делать на любом сервере. Эта модель более масштабируема, так как обновления могут происходить на различных серверах одновременно. Недостатком такой модели является большая сложность репликации. Вопросы репликации мы рассмотрим позже. □ Топология репликации является гибкой, чтобы поддерживать репликации на медленных соединениях в WAN. Как часто должны реплицироваться данные, конфигурируется администраторами доменов. □ Активный каталог поддерживает открытые стандарты. LDAP (Lightweight Directory Access Protocol — легковесный протокол доступа к каталогу), является одним из стандартов, который может использоваться для доступа к данным в активном каталоге. LDAP является стандартом Интернета, который может использоваться для доступа ко множеству различных служб каталога. Так как LDAP также является интерфейсом программирования, то определен LDAP API, который можно применять для доступа к активному каталогу с помощью языка C. Предпочтительный интерфейс программирования компании Microsoft для служб каталога — это ADSI (Active Directory Service Interface — интерфейс служб активного каталога). Его конечно, нельзя назвать открытым стандартом. В противоположность LDAP API с помощью ADSI можно получить доступ ко всем свойствам активного каталога. Другим стандартом, который используется в активном каталоге, является Kerberos. Kerberos используется для аутентификации. Служба Kerberos в Windows 2000 может также применяться для аутентификации клиентов Unix. Это не работает в обратную сторону; серверы Unix Kerberos не могут аутентифицировать клиентов Windows 2000, так как компания Microsoft расширила протокол Kerberos для своего собственного использования. □ При использовании активного каталога мы имеем детально структурированную систему безопасности. Каждый объект, хранящийся в активном каталоге, имеет связанный список управления доступом, определяющий, кто и какие действия может производить с объектом. Объекты в каталоге являются строго типизированными. Это означает, что тип объектов точно определен, к объекту нельзя добавить ни одного не специфицированного атрибута. В схеме (Schema) определены типы объектов, а также части объектов (атрибуты). Атрибуты могут быть обязательными или необязательными. Концепции активного каталогаПрежде чем программировать для активного каталога, необходимо познакомиться с некоторыми концепциями. Существует много новых терминов, которые надо знать при разговоре об активном каталоге. ОбъектыВ активном каталоге хранятся объекты. Объект — это что-то конкретное, например пользователь, принтер или общий сетевой ресурс. Объекты имеют обязательные и необязательные атрибуты, которые описывают объект. Примерами атрибутов объекта user (пользователь) являются фамилия, имя, адрес e-mail, телефонный номер и т. д. На следующем рисунке показаны: контейнерный объект Wrox Press, несколько объектов пользователей, контакт, принтер и объект группы пользователей: СхемаКаждый объект является экземпляром класса в схеме (schema). Схема хранится среди объектов активного каталога. Мы должны различать classSchemaи attributeSchema. В classSchemaопределяется тип объекта, а также данные о том, какие обязательные и необязательные атрибуты имеет объект. attributeSchemaопределяет, на что похож атрибут, и какой допустим для него синтаксис. Можно пользоваться собственными типами и атрибутами и добавить их к схеме. Помните, что новый тип схемы вам не удастся убрать из активного каталога. Можно пометить его как неактивный, чтобы новые объекты больше нельзя было создавать, но могут существовать объекты этого типа, поэтому невозможно удалить классы или атрибуты, которые определены в схеме. Windows 2000 Administrator не имеет достаточных полномочий для создания новых записей схемы, здесь нужен Windows 2000 Domain Enterprise Administrator. КонфигурацияВ активном каталоге хранятся не только объекты, но и определения классов (в схеме) и конфигурация. Конфигурация активного каталога хранит информацию обо всех сайтах, интервалах репликации и т.д., которая задается системным администратором. К конфигурационной информации можно получить доступ, как ко всем другим объектам в активном каталоге. Домен активного каталогаДомен является границей безопасности сети Windows. В домене активного каталога объекты хранятся в иерархическом порядке. Сам активный каталог состоит из одного или нескольких доменов. Иерархический порядок объектов представлен на рисунке ниже. Контейнерные объекты, такие как Users, Computersи Books, могут хранить другие объекты: На следующем рисунке мы видим домен, который представлен треугольником. Каждый овал на рисунке представляет объект, линии между объектами показывают отношения предок/потомок. Booksявляется предком для .NETи Java. Pro C#, Beg C#, и ASP.NETявляются объектами-потомками объекта .NET. Контроллер доменаОдин домен может иметь несколько серверов, каждый из которых хранит все объекты внутри домена. Не существует мастер-сервера, и все серверы интерпретируются одинаково; мы имеем модель с несколькими мастерами. Объекты реплицируются между серверами внутри домена. На следующем рисунке домен Wrox.comпредставлен треугольником. DC1 и DC2 являются двумя контроллерами домена для этого домена: СайтСайт является местоположением в сети, содержащим серверы активного каталога (контроллеры домена). Если имеется несколько местоположений на предприятии, соединенных медленными сетевыми связями, то можно использовать несколько сайтов для одного домена. Для целей резервного копирования или масштабирования каждый сайт имеет один или несколько выполняющихся контроллеров доменов. Репликация между серверами на сайте может происходить с более короткими интервалами в связи с более быстрым сетевым соединением. Репликация между серверами на различных сайтах конфигурируется с большими интервалами времени, в зависимости от скорости сети. Конечно, это может сконфигурировать администратор домена. На следующем рисунке показан один домен Wrox.com, который имеет несколько сайтов: Seattle, New York и Chicago. В каждом из этих сайтов выполняются по два контроллера домена. Дерево доменаНесколько доменов могут соединяться доверительными отношениями. Эти домены совместно используют общую схему, общую конфигурацию и глобальный каталог. Общая схема и общая конфигурация означают, что эти данные реплицируются между доменами. Деревья доменов совместно используют одну и ту же схему классов и атрибутов. Сами объекты не реплицируются между доменами. Домены, соединенные таким образом, называются деревом доменов. Домены в дереве доменов имеют непрерывное иерархическое пространство имен. Это означает, что имя домена-потомка добавляется к имени домена-предка. Между доменами устанавливаются доверительные отношения, использующие протокол Kerberos. На следующем рисунке показан корневой домен wrox.com, который является также доменом-предком доменов-потомков france.wrox.comи uk.wrox.com. Доверительные отношения задаются между доменами предком и потомком так, чтобы учетные записи одного домена можно было аутентифицировать в другом: ЛесСоединение множества деревьев доменов с помощью общей схемы, общая конфигурация и глобальный каталог без непрерывного пространства имен называется лесом. Лес является множеством деревьев доменов. Лес может иметь место, если у компании есть филиал, где должно применяться другое имя домена. Предположим, что домен asptoday.comдолжен быть относительно независимым от домена wrox.com, но должно быть общее управление, а также возможность пользователям из домена asptoday.comиметь доступ к ресурсам из домена wrox.comи наоборот. С помощью леса можно создать доверительные отношения между множеством деревьев доменов. Глобальный каталогПоиск объекта может охватывать несколько доменов. Если ищется объект определенного пользователя с некоторыми атгрибутами, то необходимо вести поиск в каждом домене. Начиная с wrox.com, поиск продолжается в uk.wrox.comи france.wrox.comчерез медленные соединения, такой поиск может потребовать достаточно много времени. Чтобы ускорить поиск, все объекты копируются в глобальный каталог. Глобальный каталог реплицируется в каждый домен леса. Существует по крайней мере один сервер в каждом домене, содержащий глобальный каталог. По соображениям производительности и масштабируемости можно иметь в домене более одного сервера с глобальным каталогом. С помощью глобального каталога поиск по всем объектам может вестись на одном сервере. На следующем рисунке мы видим три домена в дереве доменов. Каждый из этих доменов имеет глобальный каталог. По умолчанию глобальный каталог устанавливается на первом контроллере домена, но могут быть добавлены дополнительные каталоги: Глобальный каталог является для всех объектов кэш-памятью только для чтения. Каталог может применяться лишь для поиска; для выполнения обновлений должны использоваться контроллеры доменов. Не все атрибуты объекта хранятся в глобальном каталоге. Можно определить, должен ли он храниться там или нет. Решение о необходимости хранения атрибута в глобальном каталоге зависит от частоты использования его при поиске. Изображение пользователя бесполезно в глобальном каталоге, так как вряд ли поиск будет осуществиться по изображению. Вместо этого полезным добавлением для хранения был бы номер телефона. Атрибут можно также использовать для уточнения того, что он должен быть проиндексирован, с целью ускорения запроса этого атрибута. РепликацияКак программисты мы не будем конфигурировать репликацию, но так как она является важным аспектом данных, которые хранятся в активном каталоге, необходимо знать, как она работает. Активный каталог использует архитектуру серверов с несколькими мастерами. Обновления могут и будут происходить на каждом контроллере домена в домене. Задержка репликации определяет, сколько времени потребуется для выполнения обновлений. □ Конфигурируемое уведомление об изменении происходит внутри сайта по умолчанию каждые 5 минут, если изменяются некоторые атрибуты. Сервер, где происходит изменение, информирует все серверы по очереди с 30-секундным интервалом. В дальнейшем сервер может получать уведомление об изменении через 7 минут. По умолчанию уведомление об изменении между сайтами задается равным 180 минутам. Внутри- и межсайтная репликация может быть сконфигурирована на другие значения. □ Если никаких изменений не происходит, плановая репликация выполняется каждые 60 минут внутри сайта. Это служит гарантией того, что уведомление об изменении не будет пропущено. □ Для информации, чувствительной к безопасности, такой как блокирование учетной записи, может происходить немедленное уведомление. Изменения при репликации копируются в контроллеры доменов. Для каждого изменения атрибута записываются номер версии (USN — номер последовательности обновления) и отметка времени. Они используются для разрешения конфликтов, если обновления происходят в одном и том же атрибуте на различных серверах. Рассмотрим пример. Атрибут "мобильный телефон" пользователя Джона Доу имеет номер USN 47. Это значение уже реплицировано во все контроллеры доменов. Один системный администратор изменяет телефонный номер. Изменение происходит на сервере DC1, новый USN этого атрибута на сервере DC1 теперь будет 48, а остальные контроллеры доменов по прежнему имеют USN, равным 47. Если кто-то все еще читает атрибут, то он может считать старое значение, так как репликация еще не произошла на всех контроллерах доменов. Теперь может произойти редкий случай, когда другой администратор изменяет атрибут "телефонный номер", и здесь был выбран другой контроллер домена, так как этот администратор получил более быстрый ответ от сервера DC2. USN этого атрибута на сервере DC2 также изменяется на 48. Через заданный интервал происходит уведомление, так как USN атрибута изменился, и последний раз репликация происходила со значением USN, равным 47. С помощью механизма репликации теперь обнаруживается, что серверы DC1 и DC2 оба имеют USN, равный 48, для атрибута "номер телефона". Какой сервер будет победителем в действительности не имеет значения, но один сервер должен выиграть. Чтобы разрешить этот конфликт, используется отметка времени изменения. Так как изменение произошло позднее на DC2, то будет реплицировано значение, которое хранится в контроллере домена DC2.
Характеристики данных активного каталогаАктивный каталог не заменяет реляционную базу данных или реестр. Какие же данные могут там хранится? □ В активном каталоге имеются иерархические данные. Мы можем иметь контейнеры, в которых опять же хранятся контейнеры, а также объекты. Сами контейнеры тоже являются объектами. □ Данные должны использоваться в основном для чтения. Так как мы имеем репликацию, которая происходит с некоторым задаваемым интервалом времени, мы не можем быть уверены, что прочитаем своевременные данные. В приложениях необходимо учитывать, что прочитанная информация, возможно, не является реальной современной информацией. □ Данные представляют глобальный интерес для предприятия. Добавление нового типа данных в схему реплицирует его на серверы предприятия. Если типы данных представляют интерес только для небольшого числа пользователей, то администратор домена предприятия не будет устанавливать новые типы схемы. □ Данные должны иметь разумный размер в связи с репликацией. Если размер данных равен 100Кбайт, то имеет смысл хранить их в каталоге, если данные изменяются только раз в неделю. Данные такого размера слишком велики, если они изменяются каждый час. Всегда помните о репликации — куда будут пересылаться данные и с какими интервалами времени. Если имеется большой объем данных, то можно поместить в активный каталог ссылку, а сами данные хранить в другом месте. Суммируя, можно сказать, что хранимые в активном каталоге данные должны быть иерархически организованны, иметь разумный размер и быть важными для предприятия. СхемаОбъекты активного каталога являются строго типизированными. Схема определяет типы объектов, обязательные и необязательные атрибуты, а также синтаксис и ограничения атрибутов. Сама схема хранится как объекты в хранилище данных активного каталога. В схеме можно различить объекты схемы классов и схемы атрибутов. Класс является совокупностью атрибутов. С помощью классов поддерживается одиночное наследование. Как можно видеть на следующей диаграмме классов, класс userявляется производным от класса organizationalPerson, organizationalPersonявляется подклассом person, а базовым классом для всех является top. Класс classSchema, который определяет класс, описывает атрибуты с помощью атрибута systemMayContain. На диаграмме перечислены лишь немногие из всех значений systemMayContainтолько для того, чтобы передать идею конструкции. Можно легко найти все значения с помощью ADSIEdit. По корневому классу topвидно, что каждый объект может иметь атрибуты общее имя ( cn), displayName, objectGUID, whenChangedи whenCreated. Класс Personявляется производным от top. Объект Personимеет также пароль userPasswordи telephoneNumber. organizationalPersonявляется производным от Person. В дополнение к Personон имеет manager, department, company, a userимеет атрибуты, необходимые для регистрации в системе: Управление активным каталогомНа самом деле мы не будем говорить об управлении активным каталогом. За управление отвечают системные администраторы Windows 2000, а мы хотим поговорить о программировании активного каталога. Однако рассмотрение некоторых инструментов управления может помочь понять, что такое активный каталог, какие данных в нем находятся, и что можно сделать программным путем. Системный администратор имеет множество инструментов для ввода новых данных, обновления данных и для конфигурирования активного каталога. С помощью инструмента Active Directory Users and Computers (Пользователи и компьютеры активного каталога) можно обновить данные о пользователях и ввести новых пользователей. Инструмент Active Directory Sites and Services используется для конфигурирования сайтов в домене и репликации между этими сайтами. ActiveDirectory Domains and Trusts может применяться для создания доверительных отношений между доменами в дереве. Редактором реестра для активного каталога, где можно просмотреть и отредактировать каждый объект, является ADSI Edit. В дополнение к инструментам системного администратора имеется инструмент в SDK платформы Microsoft: ADSI Viewer. Active Directory Users and ComputersУтилита Active Directory Users and Computers является инструментом, который в основном служит системным администраторам для управления своими пользователями. Start|Programs|Administrative Tools|Active Directory Users and Computers: С помощью этой утилиты можно добавлять новых пользователей, группы, контакты, организационные единицы, принтеры, общие папки, компьютеры, и модифицировать существующие. На изображении ниже можно видеть атрибуты, которые вводятся для объекта пользователь (user): офис, номера телефонов, адреса e-mail, web-страницы, информация об организации, адреса, группы и т.д., т.е. значительно больше информации, чем было возможно в домене NT 4: Утилита Active Directory Users and Computers может также использоваться на больших предприятиях с миллионами объектов. Не обязательно просматривать список с тысячами объектов, можно выбрать специальный фильтр, чтобы выводились только некоторые объекты. Можно также сделать запрос LDAP для поиска объектов на предприятии. ADSI EditADSI Edit является редактором реестра активного каталога. Эта утилита не устанавливается автоматически. На компакт-диске Windows 2000 Server можно найти каталог с именем Supporting Tools. Когда утилиты поддержки будут установлены, ADSI Edit можно будет найти в меню: Start|Programs|Windows 2000 Support Tools|Tools|ADSI Edit. Простая в использовании утилита Active Directory Users and Computers имеет фиксированный интерфейс пользователя для изменения атрибутов объектов пользователя. Мы не увидим атрибутов, которые добавляются к схеме в интерфейсе пользователя этой утилиты, управляемом мышью. Все можно сконфигурировать с помощью ADSI Edit, мы можем также просмотреть схему и конфигурацию. Эта утилита, однако, не так проста в использовании, и очень легко ввести неправильные данные: Открывая окно Properties (Свойства) объекта, можно изменить любой атрибут объекта в активном каталоге. Мы видим обязательные, дополнительные атрибуты, типы и значения атрибутов: ADSI ViewerУстановим также браузер активного каталога как часть SDK платформы Microsoft. SDK платформы Microsoft не является частью дистрибутива Visual Studio.NET. Вы получаете компакт-диск с подпиской на MSDN или загружаете его с web-сайта MSDN. После установки SDK платформы можно запустить утилиту с помощью пункта меню Start|Programs|Microsoft Platform SDK|Tools|ADSI Viewer. ADSI Viewer имеет два режима. С помощью File|New можно запустить запрос или использовать Object Viewer для вывода и изменения атрибутов объектов. После запуска Object Viewer можно определить путь доступа LDAP, а также имя пользователя и пароль, чтобы открыть объект. Вскоре, когда мы начнем делать это программным путем, вы увидите, какую форму может иметь путь доступа LDAP. Здесь определяется LDAP://OU=Wrox Press, DC=eichkogelstrasse, DC=local, чтобы получить доступ к объекту организационной единицы: Если определяемый объект с путем доступа и именем пользователя и паролем является допустимым, мы получаем экран Object Viewer где можно видеть и изменять свойства объекта и объектов-потомков: Интерфейсы службы активного каталога (ADSI)Интерфейсы службы активного каталога (ADSI) являются программным интерфейсом к службам каталога. ADSI определяет некоторые интерфейсы COM, которые реализуются провайдерами ADSI. Это означает, что клиент может использовать различные службы каталога с одними и теми же программными интерфейсами. Классы среды .NET в пространстве имен System.DirectoryServicesиспользуют интерфейсы ADSI. На следующем рисунке можно видеть некоторых провайдеров ADSI (LDAP, WinNT, NDS), которые реализуют интерфейсы COM, такие как IADи IUnknown. Сборка System.DirectoryServicesиспользует провайдеров ADSI: Программирование активного каталогаЧтобы разрабатывать программы для активного каталога, мы используем классы из пространства имен System.DirectoryServices. С помощью этих классов можно запрашивать объекты, просматривать и обновлять свойства, а также вести поиск объектов. В следующих сегментах кода простое консольное приложение C# демонстрирует применение классов в пространстве имен System.DirectoryServices. Классы в System.DirectoryServicesСледующая таблица показывает основные классы в пространстве имен System.DirectoryServices:
СвязываниеЧтобы получить значения объекта в активном каталоге, мы должны соединиться с активным каталогом. Процесс соединения называется связыванием. Путь доступа связывания может выглядеть следующим образом: LDAP://dc01.globalknowledge.net/OU=Marketing, DC=GlobalKnowledge, DC=Com Во время процесса связывания можно определить следующие позиции: □ Протокол, определяющий используемого провайдера. □ Имя сервера контроллера домена. □ Номер порта серверного процесса. □ Известное имя объекта для идентификации объекта, к которому требуется доступ. □ Имя пользователя и пароль, если требуется другой пользователь для доступа к активному каталогу. □ Можно также определить тип аутентификации, если требуется шифрование. ПротоколПервая часть пути связывания определяет провайдера ADSI. Провайдер реализован как сервер COM; для идентификации можно найти идентификатор программы прямо в ключе HKEY_CLASSES_ROOT. Провайдеры, которых получают вместе с Windows 2000, перечислены в следующей таблице:
Имя сервераИмя сервера следует за протоколом в строке соединения. Имя сервера является не обязательным, если вы зарегистрировались в домене активного каталога. Без имени сервера происходит связывание без сервера; это означает, что Windows 2000 пытается получить "лучший" контроллер домена в домене, который ассоциирован с пользователем, выполняющим связывание. Если внутри сайта нет сервера, будет использоваться первый найденный контроллер домена. Связывание без сервера может выглядеть следующим образом: LDAP://OU=Sales, DC=GlobalKnowladge, DC=Com. Номер портаПосле имени сервера можно определить номер порта серверного процесса, используя синтаксис :xxx. По умолчанию для сервера LDAP используется номер порта 389: LDAP://dc01.globalknowledge.net:389. Сервер Exchange использует тот же самый номер порта, что и сервер LDAP. Если сервер Exchange установлен на той же системе, например, как контроллер домена активного каталога, то можно сконфигурировать другой порт. Известное имяЧетвертая часть, которую мы должны определить в пути доступа,— это известное имя (DN — Distinguished Name). Известное имя является гарантированным уникальным именем, идентифицирующим объект, к которому требуется доступ. В активном каталоге для определения имени объекта можно использовать синтаксис LDAP, который основывается на X.500. Известное имя CN=Christian Nagel, OU=Trainer, DC=GlobalKnowledge, DC=com определяет общее имя ( CN) Christian Nagel в организационной единице ( OU) Trainer в компоненте домена ( DC) GlobalKnowledge домена GlobalKnowledge.com. Часть, которая определена самой правой является корневым объектом домена. Имя должно следовать иерархии дерева объектов. Спецификацию LDAP для строкового представления известных имен можно найти в RFC 2253: www.ietf.org/rfc/rfc2253.txt. Относительное известное имя Относительное известное имя (RDN) используется для ссылки на объект внутри контейнерного объекта. Для RDN спецификации OU и DC не требуются, будет достаточно общего имени. CN=Christian Nagelявляется относительным известным именем внутри организационной единицы. Относительное известное имя может использоваться, если мы уже имеем ссылку на объект контейнера и хотим получить доступ к объектам-потомкам. Используемый по умолчанию именующий контекст Если известное имя не определено в пути доступа, процесс связывания будет выполняться в используемом по умолчанию именующем контексте. Можно считать используемый по умолчанию именующий контекст с помощью rootDSE. LDAP 3.0 определяет rootDSE как корень дерева каталогов на сервере каталога. LDAP://rootDSEили LDAP://servername/rootDSE Перечисляя все свойства rootDSE, можно получить информацию о defaultNamingContext, который будет использоваться, когда не определено никакое имя. schemaNamingContextи configurationNamingContextопределяют требуемые имена, которые будут использоваться для доступа к схеме и конфигурации в хранилище активного каталога. Следующий код используется для получения всех свойств rootDSE. Речь идет о связывании с помощью класса DirectoryEntry: using (DirectoryEntry de = new DirectoryEntry()) { de.Path = "LDAP://celtlcrain/rootDSE"; de.Username = @"sentinel\chris"; de.Password = "mausemaus3"; PropertyCollection props = de.Properties; foreach (string prop in props.PropertyNames) { PropertyValueCollection values = props[prop]; foreach (string val in values) { Console.Write(prop + ": "); Console.WriteLine(val);. } } } Помимо других свойств результат вывода этой программы показывает defaultNamingContext DC=eichkogelstrasse, DC=local, контекст, который можно использовать для доступа к схеме: CN=Schema, CN=Configuration, DC=eichkogelstrasse, DC=localи именующий контекст конфигурации: CN=Configuration, DC=eichkogelstrasse, DC=local: Идентификатор объекта Каждый объект имеет уникальный идентификатор — GUID. GUID является уникальным 128-битовым числом. Мы можем с соединиться с объектом, используя GUID. Таким образом, мы всегда получаем тот же самый объект, даже если объект был перемещен в другой контейнер. GUID генерируется при создании объекта и всегда остается тем же самым. Можно получить строковое представление GUID с помощью DirectoryEntry.NativeGuid. Затем это строковое представление можно использовать для соединения с объектом. Даже если объект перемещается в другой контейнер, мы всегда получаем тот же объект. Следующий пример показывает имя пути доступа для связывания без сервера со специфическим объектом, представленным GUID: LDAP://<GUID=14abbd652aae1a47abc60782dcfc78ea>Имена объектов в доменах Windows NT Провайдер WinNT не допускает синтаксис LDAP в части имени строки связывания. Для этого провайдера объект определяется с помощью ObjectName, ClassName. Действительные строки связывания для домена Windows NT имеют следующий вид: WinNT: WinNT://DomainName WinNT://DomairName/UserName, user WinNT://DomainName/dc01/MyGroup, group Имя пользователяЕсли другой пользователь, отличный от зарегистрированного, должен использоваться для доступа к каталогу, так как зарегистрированный пользователь не имеет требуемых полномочий для доступа к активному каталогу, то должны определяться явные полномочия пользователя для процесса связывания. Для активного каталога имеется ряд способов задания имени пользователя. Низкоуровневая регистрацияДля низкоуровневой регистрации имя пользователя можно определить с помощью имени домена: domain\usernameИзвестное имя Пользователя можно определить также с помощью известного имени объекта пользователя, например: CN=Administrator, CN=Users, DC=eichkogelstrasse, DC=localИмя пользователя принципала (UPN) UPN объекта определяется с помощью атрибута userPrincipalName. Системный администратор определяет его по информации регистрации на вкладке Accountсвойств Userс помощью утилиты Active Directory Users and Computers. UPN не является адресом e-mail пользователя Эта информация также уникальным образом определяет пользователя и может использоваться для регистрации: Nagel@eichkogestrasse.local АутентификацияДля безопасной зашифрованной аутентификации можно также определить тип аутентификации. Аутентификация может задаваться с помощью свойства AuthenticationTypeкласса DirectoryEntry. При этом присваиваемое значение является одним из перечислений AuthenticationTypes. Связывание с помощью класса DirectoryEntryКласс System.DirectoryServices.DirectoryEntryиспользуется для определения всех связываемых данных. Можно использовать конструктор по умолчанию и определить данные связывания со свойствами Path, Username, Passwordи AuthenticationTypeили передать всю информацию в конструктор: using (DirectoryEntry de = new DirectoryEntry()) { de.Path = "LDAP://celticrain/DC=eichkogelstrasse, DC=local"; de.Username = "nagel@eichkogelstrasse.local"; de.Password = "someSecret"; // использовать полномочия текущего пользователя DirectoryEntry de2 = new DirectoryEntry("LDAP://DC=eichkogelstrasse, DC=local"); Даже если создание объекта DirectoryEntryпройдет успешно, это не означает, что и связывание было успешным. Связывание произойдет, когда в первый раз будет прочитано свойство во избежание ненужного сетевого трафика. Существует ли объект или правильны ли полномочия определенного пользователя, можно будет увидеть при первом доступе к объекту. Получение записей каталогаТеперь, когда мы знаем, как определить атрибута связывания с объектом в активном каталоге, давайте прочитаем атрибуты объекта. Свойства объектов пользователейКласс DirectoryEntryимеет некие свойства Name, Guidи SchemaClassNameдля получения информации об объекте. Первый раз при доступе к свойству объекта DirectoryEntryпроисходит связывание и заполняется кэш. Когда мы обращаемся к другому свойству, мы считываем его из кэша, и коммуникации с сервером не требуется для данных из того же объекта. В следующем примере мы обращаемся к объекту пользователя с общим именем Christian Nagel в организационной единице Wrox Press. DirectoryEntry de = new DirectoryEntry(); de.Path = "LDAP://celticrain/CN=Christian Nagel, " + "OU=Wrox Press, DC=eichkogelstrasse, DC=local"; Console.WriteLine("Name: "+ de.Name); Console.WriteLine("GUID: " + de.Guid); Console.WriteLine("Type: " + de.SchemaClassName); Console.WriteLine(); Объект активного каталога содержит значительно больше информации. Доступность информации зависит от типа объекта. Чтобы получить всю информацию об объекте, свойство Propertiesвозвращает PropertyCollection. Каждое свойство само является коллекцией, так как одно свойство может иметь несколько значений, например, объект пользователя может иметь несколько телефонных номеров. Мы перебираем значения с помощью внутреннего цикла foreach. Коллекция, которая возвращается из properties[name]является массивом объектов. Значения атрибутов могут быть строками, числами или другими типами данных. Мы используем метод ToString()для вывода значений. Console.WriteLine("Attributes: "); PropertyCollection properties = de.Properties; foreach (string name in properties.PropertyNames) { foreach (object о in properties[name]) { Console.WriteLine(name + ": " + o.ToString()); } } В выходных результатах мы видим все атрибуты объекта пользователя Christian Nagel. Заметим, что otherTelephone является многозначным свойством, которое содержит несколько телефонных номеров. Некоторые из значений свойств просто выводят тип объекта System._ComObject. Чтобы получить значения этих атрибутов, необходимо непосредственно использовать интерфейсы ADSI COM, которые также берутся из классов в пространстве имен System.DirectoryServices. Доступ к свойствам непосредственно по имени С помощью DirectoryEntry.Propertiesможно получить доступ ко всем свойствам. Если имя свойства известно, можно получить значение непосредственно: foreach (string homePage in de.Properties["wWWHomePage"]) Console.WriteLine("Home page; " + homePage); Коллекции объектовОбъекты хранятся в активном каталоге иерархически. В контейнерных объектах содержатся объекты-потомки. Их можно перечислить с помощью свойства Childrenкласса DirectoryEntry. В другом направлении можно получить контейнер объекта с помощью свойства Parent. Объект пользователя не имеет потомков, поэтому воспользуемся теперь организационной единицей. Давайте получим все объекты пользователей из организационной единицы Wrox Press в домене eichkogelstrasse.local. Свойство Childrenвозвращает коллекцию DirectoryEntries, которая содержит объекты DirectoryEntry. Мы просматриваем все объекты DirectoryEntryдля вывода имен объектов-потомков: DirectoryEntry de = new DirectoryEntry(); de.Path. = "LDAP://celticrain/OU=Wrox Press, " + "DC=eichkogelstrasse, DC=local"; Console.WriteLine("Children of " + de.Name); foreach (DirectoryEntry obj in de.Children) { Console.WriteLine(obj.Name); } В данном примере мы видим все объекты в организационной единице: пользователей, контакты, принтеры, общие ресурсы и другие организационные единицы. Если нужно увидеть только некоторые типы объектов, можно использовать свойство SchemaFilterкласса DirectoryEntries: DirectoryEntry de = new DirectoryEntry(); de.Path = "LDAP://celticrain/OU=Wrox Press, " + "DC=eichkogelstrasse, DC-local"; Console.WriteLine("Children of " + de.Name); de.Children.SchemaFilter.Add("user"); foreach(DirectoryEntry obj in de.Children) { Console.WriteLine(obj.Name); } В результате мы видим в организационной единице только объекты пользователей: КэшЧтобы уменьшить сетевой трафик, ADSI использует кэш для свойств объектов. Как было показано ранее, обращение к серверу не происходит при создании объекта DirectoryEntry, а происходит, когда впервые считывается значение из хранилища каталога. При считывании первого свойства все свойства записываются в кэш, поэтому повторное обращение к серверу не нужно, когда считывается следующее свойство. Этот кэш свойств может быть выключен при задании свойства DirectoryEntry.UsePropertyCacheкак false. Лучше этого не делать, так как это будет порождать множество ненужных обращений к серверу. Запись изменений в объекты также происходит только в кэше. Задание множества свойств не генерирует сетевого трафика. Метод DirectoryEntry.CommitChanges()требуется для очистки кэша и переноса всех измененных данных на сервер. Чтобы снова получить вновь записанные данные из хранилища каталога, можно для чтения свойств использовать метод DirectoryEntry.RefreshCache(). Задание свойства UsePropertyCacheкак falseможет быть очень полезно для отладки, чтобы увидеть, какое свойство было изменено неправильно. Обновление записей каталогаОбъекты в активном каталоге обновляются так же легко, как и читаются. Изменение значений возможно после считывания объекта. Чтобы удалить все значения одного свойства, может вызываться метод PropertyValueCollection.Clear(). С помощью метода Add()к свойству могут добавляться новые значения. Remove()и RemoveAt()удаляют специфические значения из коллекции свойства: using (DirectoryEntry de = new DirectoryEntry!)) { de.Path = "LDAP://celticrain/CN=Christian Nagel, " + "OU=Wrox Press, DC=eichkogelstrasse, DC=local"; if (de.Properties.Contains("mobile")) { de.Properties["mobile"][0] = "+43 (664) 3434343434"; } de.CommitChanges(); } Чтобы изменить значение, зададим ему определенное значение. Посредством следующей строки кода для номера мобильного телефона задается новое значение, если оно существует, с использованием индекса PropertyValueCollection. С помощью индекса значение может только изменяться. Поэтому необходимо всегда проверять методом DirectoryEntry.Properties.Contains(), доступен ли атрибут: de.Properties["mobile"][0] = "+43 (664) 3434343434";
Создание новых объектовНовые объекты активного каталога, такие как пользователи, компьютеры, принтеры, контакты и другие программным путем можно создать с помощью класса DirectoryEntries. Чтобы добавить новые объекты в каталог, мы должны сначала соединиться с объектом-контейнером, подобным организационной единице, куда можно вставить новые объекты. Объекты, которые не могут содержать другие объекты, использовать нельзя. Здесь используется контейнерный объект с известным именем CN=Users, DC=eichkogelstrasse, DC=local: DirectoryEntry de = new DirectoryEntry(); de.Path = "LDAP://celticrain/CN=Users, " + "DC=eichkogelstrasse, DC=local"; Можно получить доступ к объекту DirectoryEntriesс помощью свойства Childrenобъекта DirectoryEntry: DirectoryEntries users = de.Children; Объект DirectoryEntriesимеет методы для добавления, удаления, и поиска объектов в коллекции. Здесь создается новый объект пользователя. Для метода Add()нам нужно имя объекта и имя типа. Можно легко получить имена типов с помощью ADSI Edit. DirectoryEntry user = users.Add("John Doe", "user"); Объект теперь имеет значения свойств по умолчанию. Чтобы присвоить специальные значения свойств, можно добавить свойства с помощью метода Add()свойства Properties. Конечно, все свойства должны существовать в схеме для объекта пользователя. Если определенное свойство не существует, то возникнет исключение COMException"The specified directory service attribute or value doesn't exist" ("Указанный атрибут или значение службы каталога не существует"). Если имена атрибутов правильны, но сервер отказывает во входе в связи с незаконным паролем или пропущенным свойством, исключение COMExceptionбудет содержать сообщение "The server is unwilling to process the request" ("Сервер не желает обрабатывать запрос"). user.Properties["company"].Add("Some Company"); user.Properties["department"].Add("Sales"); user.properties["employeeID"].Add("4711"); user.Properties["samAccountName"].Add("John Doe"); user.Properties["userPassword"].Add("someSecret"); В данный момент не все данные записаны в активный каталог. Необходимо очистить кэш: user.CommitChanges(); Поиск в активном каталогеБольшую часть времени активный каталог будет использоваться для поиска некоторых значений. Это хранилище данных, которое оптимизировано в основном для чтения, поэтому данные будут в основном считываться. Для поиска в активном каталоге платформа .NET имеет класс DirectorySearcher.
В конструкторе класса DirectorySearcherсуществуют четыре важные части поиска. Можно также использовать конструктор по умолчанию и определять параметры поиска с помощью свойств. SearchRoot Корень поиска ( SearchRoot) определяет, где должен начаться поиск. По умолчанию SearchRootявляется корнем домена, который используется в данный момент. SearchRootопределен с помощью свойства Pathобъекта DirectoryEntry. Filter Фильтр (Filter) определяет значения, которые мы хотим найти. Фильтр является строкой, которая должна быть заключена в круглые скобки. Операторы отношений, такие как <=, =, >=, в выражениях допускаются. ( objectClass = contact) будет искать все объекты типа contact; ( lastName>=Nagel) ищет все объекты, где свойство lastNameравно или больше Nagel, что означает, что оно следует за ним в алфавитном порядке. Выражения могут комбинироваться с префиксными операциями &и |. ( &(objectClass=user)(description=Auth*)) ищет все объекты типа user, где свойство descriptionначинается со строки Auth. Так как операторы &и |находятся в начале выражения, то с помощью одного префиксного оператора можно комбинировать более двух выражений. По умолчанию используется фильтр ( objectClass=*), поэтому все объекты допустимы. Синтаксис фильтра определен в RFC 2254, "Строковое представление фильтров поиска LDAP". Этот RFC можно найти по адресу www.ietf.org/rfc/rfc2254.txt. PropertiesToLoad С помощью PropertiesToLoadмы определяем коллекцию StringCollectionвсех интересующих нас свойств. Как вы уже видели, объекты могут иметь множество свойств. Большинство из них будут не важны для нашего запроса поиска. Мы определяем свойства, загружаемые в кэш. Свойствами по умолчанию, которые мы получаем, если ничего не определено, являются Pathи Nameдля объекта. SearchScope SearchScopeявляется перечислением, которое определяет, как глубоко должен распространяться поиск: □ SearchScope.Baseищет атрибуты только в том объекте, где начинается поиск, поэтому мы получаем максимум один объект. □ Для SearchScope.OneLevelпоиск продолжается в коллекции-потомке базового объекта. Сам базовый объект для поиска не используется. □ SearchScope.Subtreeопределяет, что поиск должен спускаться вниз по всему дереву. По умолчанию для SearchScopeиспользуется Subtree. Пределы поискаТакой поиск может охватывать несколько доменов. Чтобы ограничить поиск некоторым числом объектов или требуемым временем, необходимо определить несколько дополнительных свойств.
В рассматриваемом примере поиска мы хотим найти все объекты пользователей в организационной единице Wrox Press, где свойство descriptionсодержит значение Author. Сначала мы соединяемся с организационной единицей Wrox Press. Здесь начинается поиск. Создадим объект DirectorySearcher, где задан SearchRoot. Фильтр определяется как ( &(objectClass=user)(description=Auth*)) для того, чтобы мы нашли все объекты типа user, где свойство descriptionначинается с последовательности Auth, за которой может следовать что-то еще. Область поиска должна быть поддеревом, чтобы поиск происходил в порождаемых организационных единицах для Wrox Press: DirectoryEntry de new DirectoryEntry(); de.Path = "LDAP://OU=Wrox Press, " + "DC=eichkogelstrasse, DC=local"; DirectorySearcher searcher = new DirectorySearcher(); searcher.SearchRoot = de; searcher.Filter = "(&(objectClass=user)(description=Auth*))"; searcher.SearchScope = SearchScope.Subtree; В результате поиска мы хотим получить свойства name, description, givenName, и wWWHomePage. searcher.PropertiesToLoad.Add("name"); searcher.PropertiesToLoad.Add("description"); searcher. PropertiesToLoad.Add("givenName"); searcher.PropertiesToLoad.Add("wWWHomePage"); Мы готовы начать поиск. Однако, результат необходимо отсортировать. DirectorySearcherимеет свойство Sort, где можно задать SortOption. Первый аргумент конструктора SortOptionопределяет свойство, по которому будет проводиться сортировка, второй аргумент определяет направление сортировки. Перечисление SortDirectionимеет значения Ascendingи Descending. Чтобы начать поиск, можно использовать метод FindOne()для нахождения первого объекта или FindAll(), чтобы найти все объекты. FindOne()вернет простой SearchResult, FindAll()вернет SearchResultCollection. Мы хотим получить всех авторов, поэтому используем FindAll(): searcher.Sort = new SortOption("givenName", SortDirection.Ascending); SearchResultCollection Results = searcher.FindAll(); С помощью цикла foreachмы получаем доступ ко всем SearchResultв SearchResultCollection. SearchResultпредставляет один объект в кэше поиска. Свойство Propertiesвозвращает ResultPropertyCollection, где мы получаем доступ ко всем свойствам и значениям по имени свойства и по индексу. SearchResultCollection results = Searcher.FindAll(); foreach (SearchResult result in results) { ResutPropertyCollection props = result.Properties; foreach (string propName in props.PropertyNames) { Console.Write(propName + ": "); Console.WriteLine(props[propName][0]); } Console.WriteLine(); } } Если необходимо получить весь объект после поиска, то это также возможна. SearchResultимеет метод GetDirectoryEntry(), который возвращает соответствующую запись DirectoryEntryнайденного объекта. Результирующий вывод показывает начале списка всех авторов книги Professional C# с выбранными свойствами Поиск объектов пользователейПоследнее приложение, которое будет создано в этой главе, это приложение Windows Forms. С его помощью можно найти все объекты пользователей домена с динамически определяемой строкой фильтра. Можно также задать свойства объектов пользователей, которые должны выводиться. Интерфейс пользователяИнтерфейс пользователя выводит нумерованные шаги, помогая использовать приложение. 1. На первом шаге можно ввести имя пользователя, пароль и контроллер домена. Вся эта информация является необязательной. Если контроллер домена не вводится, то соединение работает со связыванием без сервера. Если отсутствует имя пользователя, то используется контекст безопасности текущего пользователя. 2. С помощью кнопки все имена свойств объекта Userмогут загружаться динамически в окно списка ListBoxProperties. 3. После загрузки имен свойств, можно выбрать свойства, которые должны выводиться. Режим SelectionModeокна списка задач как MultiSimple. 4. Можно ввести фильтр для ограничения поиска. Значение по умолчанию, которое задается в этом диалоговом окне, ищет все объекты пользователей: ( objectClass=user). 5. Теперь можно начать поиск. Получение именующего контекста схемыЭто приложение имеет только два метода обработки событий: первый метод — обработчик для кнопки загрузки свойств и второй — для запуска поиска в домене. В первой части мы динамически считываем свойства класса Userиз схемы для вывода его в интерфейсе пользователя. В методе-обработчике buttonLoadProperties_Click()с помощью метода SetLogonInformation()имя пользователя, пароль и имя хоста считываются во время диалога и сохраняются в членах класса. Затем метод SetNamingContext()задает имя LDAP схемы и имя LDAP используемого по умолчанию контекста. Имя LDAP этой схемы используется в вызове SetUserProperties()для задания свойств в окне списка: private void buttonLoadProperties_Click(object sender, System.EventArgs e) { try { SetLogonInformation(); SetNamingContext(); SetUserProperties(schemaNamingContext); } catch (Exception ex) { MessageBox.Show("Cheek your inputs! " + ex.Message); } } protected void SetLogonInformation() { username = (textBoxUsername.Text == "" ? null : textBoxUsername.Text); password = (textBoxPassword.Text == "" ? null : textBoxPassword.Text); hostname = textBoxHostname.Text; if (hostname ! = "") hostname += "/"; } Во вспомогательном методе SetNamingContext()мы используем корень дерева каталога для получения свойств сервера. Мы заинтересованы в значениях двух свойств: SchemaNamingContext. protected string SetNamingContext() { using (DirectoryEntry de = new DirectoryEntry()) { string path = "LDAP://" + hostname + "/rootDSE"; de.Username = username; de.Password = password; de.Path = path; schemaNamingContext = de.Properties["schemaNamingContext"][0].ToString(); defaultNamingContext = de.Properties["defaultNamingContext"][0].ToString(); } } Получение имен свойств класса пользователяУ нас есть имя LDAP для доступа к схеме. Можно использовать его для доступа к каталогу и для считывания свойств. Мы заинтересованы не только в свойствах класса User, но также в свойствах базовых классов для User: Organizational-Person, Personи Top. В этой программе имена базовых классов жестко закодированы. Можно было бы прочитать базовый класс динамически с помощью атрибута subClassOf. Метод GetSchemaProperties()возвращает строковый массив со всеми именами свойств определенного типа объектов. Все имена свойств собраны в объекте propertiesтипа StringCollection: protected void SetUserProperties(string schemaNamingContext) { StringCollection properties = new StringCollection(); string[] data = GetSchemaProperties(schemaNamingContext, "User"); properties.AddRange(GetSchemaProperties(schemaNamingContext, "Organizational-Person")); properties.AddRange(GetSchemaProperties(schemaNamingContext, "Person")); properties.AddRange(GetSchemaProperties(schemaNamingContext, "Top")); listBoxProperties.Items.Clear(); foreach (string s in properties) { listBoxProperties.Items.Add(s); } } В методе GetSchemaProperties()мы снова обращаемся к активному каталогу. В этот раз вместо rootDSEиспользуется имя LDAP в схеме, которое мы обнаружили ранее. Свойство systemMayContainсодержит коллекцию всех атрибутов, которые допустимы в классе objectType: protected string[] GetSchemaProperties(string schemaNamingContext, string objectType) { string [] data; using (DirectoryEntry de = new DirectoryEntry()) { de.Username = username; de.Password = password; de.Path = "LDAP://" + hostname + "/CN=" + objectType + "," + schemaNamingContext; DS.PropertyCollection properties = de.Properties; DS.PropertyValueCollection values = properties["systemMayContain"]; data = new String[values.Count]; values.CopyTo(data, 0); } return data; } Одно интересное замечание к этому коду: в приложении Windows Forms класс PropertyCollectionпространства имен System.DirectoryServicesимеет конфликт имен с System.Data.PropertyCollection. Поскольку писать такие длинные имена как System.DirectoryServices.PropertyCollectionне всегда хочется, то с целью разрешения конфликта имя пространства имен можно сократить с помощью namespace DS = System.DirectoryServices; Именно отсюда появляется DS.PropertyCollection. Шаг 2 приложения завершен. Окно списка ( listbox) содержит все имена свойств объектов User. Поиск объектов UserОбработчик для кнопки поиска вызывает вспомогательный метод FillResult(): private void buttonSearch_Click(object render, System.EventArgs e) { try { FillResult(); } catch (Exception ex) { MessageBox.Show("Check your input: " + ex.Message) } } В методе FillResult()выполняется обычный поиск в полном домене активного каталога, как мы видели раньше. SearchScopeзадается как Subtree, Filterдля строки мы получаем из TextBox, а свойства, которые должны быть загружены в кэш, задаются значениями, которые пользователь выбирает в окне списка protected void FillResult() { using (DirectoryEntry root = new DirectoryEntry()) { root.Username = username; root.Password = password; root.Path = "LDAP://" + hostname + defaultNamingContext; using (DirectorySearcher searcher = new DirectorySearcher()) { seacher.SearchRoot = root; searcher.SearchScope = SearchScope.Subtree; searcher.Filter = textboxfilter.Text; searcher.PropertiesToLoad.AddRange(GetProperties()); SearchResultCollection results = searcher.FindbAll(); StringBuilder summary = new StringBuilder(); foreach (SearchResult result in results) { foreach (string propName in result.Properties.PropertyNames) { foreach (string s in result.Properties[propName]) { summary.Append(" " + propName + ": " + s + "\r\n"); } } summary.Append("\r\n"); } textBoxResults.Text = summary.ToString(); } } } Запустив приложение, мы получим список всех объектов, которые прошли через фильтр: ЗаключениеВ этой главе рассматривалась архитектура активного каталога, важные концепции о доменах, деревьях и лесах. Теперь мы можем получить информацию обо всем предприятии. Создавая приложения, которые обращаются к активному каталогу, необходимо знать, что данные, которые мы считываем, возможно, не являются современными в связи с задержкой репликации. С помощью классов из пространства имен System.DirectoryServicesмы получаем простые способы доступа к активному каталогу для провайдеров ADSI. Класс DirectoryEntryделает возможным чтение и запись объектов непосредственно в хранилище данных. С помощью класса DirectorySearcherможно выполнять сложный поиск и определять фильтры, задержки времени, свойства для загрузки, и область действия. Используя глобальный каталог, мы ускоряем поиск объектов по всему предприятию так как он хранит версию только для чтения всех объектов леса. |
|
||||||||||||||||||||||||||||||||||
Главная | В избранное | Наш E-MAIL | Добавить материал | Нашёл ошибку | Наверх | ||||||||||||||||||||||||||||||||||||
|