Исходники.Ру - Программирование
Исходники
Статьи
Книги и учебники
Скрипты
Новости RSS
Магазин программиста

Главная » Статьи по программированию » .NET - Framework »

Обсудить на форуме Обсудить на форуме

Работа с Active Directory с помощью технологии Microsoft .NET
В настоящее время у разработчиков периодически возникает задача получать данные о различных компонентах напрямую из Active Directory, например получить список пользовательских учётных записей, информации о пользователе, будь то имя, фамилия, принадлежность к группам и другую полезную информацию, которая хранится в Active Directory. Надо отметить, что технология .NET предоставляет разработчику достаточное колиество средств для работы с Active Directory, о которых я постараюсь рассказать читателям, но сначала мы вспомним о том, что представляет из себя Active Directory.
В настоящее время у разработчиков периодически возникает задача получать данные о различных компонентах напрямую из Active Directory, например получить список пользовательских учётных записей, информации о пользователе, будь то имя, фамилия, принадлежность к группам и другую полезную информацию, которая хранится в Active Directory. Надо отметить, что технология .NET предоставляет разработчику достаточное колиество средств для работы с Active Directory, о которых я постараюсь рассказать читателям, но сначала мы вспомним о том, что представляет из себя Active Directory.

Архитектура Active Directory

Объект Active Directory - набор атрибутов, которыми представлен сетевой ресурс, например, учётная запись пользователя. Атрибут - характеристика объекта в каталоге. Например у учётной записи пользователя есть атрибуты: имя, фамилия, адрес электронной почты. В AD объекты, как правило, организовываются в классы, т.е. в логические группы. Объекты, которые способны содержать другие объекты, называются контейнерами. К примеру, домен - контейнерный объект, который может содержать пользователей, компьютеры и другие объекты. Схема Active Directory - список определений, задающих виды объектов, которые могут храниться в Active Directory. В схеме существуют два типа определений: атрибуты и классы. Они также называются объектами схемы или метаданными. Каждый класс объекта является совокупностью атрибутов и описывает, какие объекты Active Directory можно создавать. При создании объекта атрибуты сохраняют описывающую его информацию. Опытный разработчик имеет возможность просматривать и редактировать схему с помощью штатной оснастки “Active Directory Schema”, которая не устанавливается по умолчанию в меню “Administration Tools”. Её можно установить используя Add/Remove Programs. Объекты Active Directory идентифицируются по имени. Применяются различные методы именования: составное имя(DN), онтосительное составное имя(RDN), GUID и основное имя принципала(UPN). Атрибуты составного имени: DC- имя компонента домена, OU-имя ОП, CN-общее имя. Пример составного имени: DC=RU/DC=DOMAIN/OU=ITdepartment/CN=Users/CN=Ivan Petrov. В рамках данной статьи мы будем работать с составным именем. Вспомним о том, как информация хранится в AD и как получить к ней доступ.

Самым низким уровнем является хранилище данных (файл NTDS.DIT), который располагается в папке %SYSTEMROOT%/NTDS на контроллере домена. Следующий уровень - расширяемое ядро хранения, которое взаимодействует с записями в хранилище данных на основе атрибута RDN. Над ними уровень БД и системный агент каталога(DSA), который выстраивает иерархию родительско-дочерних отношений в каталоге, а также предоставляет API для доступа к каталогу. Для связи с DSA используется протокол LDAP. Общепринятый стандарт LDAP(Lightweight Directory Access Protocol) является основным протоколом, используемым для доступа к Active Directory. Протокол LDAP версии 3 был определён группой IETF, стандартизован (RFC 1779) и используется клиентами Windows 2000,XP, 98/95(с установленными компонентами AD) для доступа к DSA. Для просмотра и редактирования Active Directory поставляется snap-in “ADSI Edit”. Для доступа к Active Directory с помощью ADSI Edit используется LDAP, поэтому для программного обращения к объектам Active Directory также целесообразно использовать LDAP URL.

Пример: LDAP://server.domain.ru/CN=Ivan Petrov/CN=Users/DC=DOMAIN/DC=RU. Где server.domain.ru - сервер, на котором расположены службы Active Directory.

Компоненты .NET Framework для работы с Active Directory.

Основным средством работы с Active Directory является объект System.DirectoryServices, хранящийся в System.DirectoryServices.dll. Поэтому перед тем как начать работать, добавьте библиотеку System.DirectoryServices.dll в References вашего проекта. И подключите пространство имён System.DirectoryServices, используя директиву using. В пространство имён System.DirectoryServices включены два оcновных компонента класса: DirectoryEntry и DirectorySearcher, которые используют технологию ADSI(Active Directory Services Interfaces). Эти классы могут быть использованы с любым из сервис провайдеров Active Directory, такими как Internet Information Services (IIS), Lightweight Directory Access Protocol (LDAP), Novell NetWare Directory Service (NDS), и WinNT. В рамках данной статьи рассмотрим работу с Active Directory по протоколу LDAP.

Объект DirectoryEntry.
Для того чтобы начать просмотр дерева, нужно подключиться к корневому контейнеру домена. Предположим, что домен называется DOM.RU, а домен контроллер называется DC. Для подключения к корню домена, создадим следующий объект:

DirectoryEntry objDirEnt = new DirectoryEntry(“LDAP://dc.dom.ru/DC=dom,DC=ru”); При этом, у объекта objDirEnt нам наиболее интересными являются свойства Children (тип DirectoryEntries ) -коллекция дочерних объектов текущего контейнера, и строковые свойства Name и Path. Path - путь к текущему объекту (в нашем случае вернёт результат “LDAP://dc.dom.ru/DC=dom,DC=ru” ), Name - имя компонента домена(вернёт “DC=dom”). Просматривать коллекцию objDirEnt.Chidren можно приблизительно таким спообом:

string DirNodePath=””;
foreach (DirectoryEntry childDirEnt in objDirEnt.Children)
	{
	DirNodePath=childDirEnt.Path;
	}

В свою очередь просматривая дочерние объкты childDirEnt мы сможем добраться до объекта любого уровня вложенности в каталоге. К родительскому контейнеру можно обратиться используя свойство Parent объекта типа DirectoryEntry.

Например:

DirectoryEntry rootEntry=new DirectoryEntry("LDAP://dc.dom.ru/CN=Ivan 

Petrov/CN=Users/DC=DOM/DC=RU");
string parentContainerPath=rootEntry.Parent.Path;

Строка parentContainerPath примет вид “LDAP://dc.dom.ru/CN=Users/DC=DOM/DC=RU”. Ещё одним интересным для нас свойством объекта DirectoryEntry является свойство Properties. Это свойство используется для вывода значений атрибутов объекта Active Directory. Например, для просмотра значений атрибутов учетной записи пользователя Ivan Petrov, Можно использовать следующую конструкцию:

 

DirectoryEntry rootEntry=new DirectoryEntry("LDAP://dc.dom.ru/CN=Ivan 

Petrov/CN=Users/DC=DOM/DC=RU");
 
foreach (string propName in rootEntry.Properties.PropertyNames) {
   foreach (object value in rootEntry.Properties[propName] ) {
     Console.WriteLine("name=" + propName + "  value=" + value );
   }
 }

С помощью просмотра значений атрибутов можно узнать практически все настройки текущего пользователя, например членство в группах(значение атрибута memberOf), номер телефона(значение атрибута telephoneNumber) и email(атрибут mail). Заметим также, что в коллекцию Properties попадают атрибуты, значение которых не null. Поэтому видим мы значительно меньшее количество атрибутов, чем есть на самом деле. Сравните список атрибутов, которые вам показывает ADSI Edit и то, что выдала программа. Имеет смысл обратить внимание, что не все значения атрибутов имеют тип string, поэтому в ваших руках обработка этих значений. Например, атрибут logonHours имеет тип System.Byte[], т.е. должна быть предусмотрена соответствующая обработка :

System.Byte[] logonHours=(System.Byte[])objDirEnt.Properties["logonHours"].Value;
foreach (byte bt in logonHours)
{
	Console.Write(bt.ToString()+ " " );
}

У возврата значений атрибутов есть особенность. Некоторое значния атрибутов, например, lastLogon будут иметь тип System.__ComObject. Для того, чтобы перевести их в удобный для разработчика вид, необходимо задействовать библиотеку типов Active Directory (system32\activeds.tlb). Я не буду углубляться в тему маршалинга, т.к. об этом написано много статей, приведу только пример, как вывести значение атрибута, имеющего тип System.__ComObject. Добавьте reference на библиотеку типов Active Directory Type Library(activeds.tlb) и добавьте её пространство имён директивой using.

using ActiveDs;
using System.Runtime.InteropServices;

LargeIntegerClass li;  
//Класс, включённый в библиотеку Active Directory Type Library
DirectoryEntry UserEntry;
UserEntry = new DirectoryEntry("LDAP://dc.dom.ru/CN=Ivan 
Petrov,CN=Users,DC=dom,DC=ru");
PropertyCollection pcoll = UserEntry.Properties;
li = (LargeIntegerClass)Marshal.CreateWrapperOfType(pcoll["lastLogon"][0], 

typeof(LargeIntegerClass));
long date = (((long)(li.HighPart) << 32) + (long) li.LowPart);
Marshal.ReleaseComObject(li);  
Console.WriteLine("DATE = {0:D}" ,DateTime.FromFileTime(date));

Чтобы поменять значение атрибута, например номер телефона, можно воспользоваться следующей конcтрукцией:
objDirEnt.Properties["telephoneNumber"][0]="+7-095-000-00-00";
objDirEnt.CommitChanges();
Однако надо иметь ввиду, что неправильные изменения Active Directory могут иметь за собой тяжёлые последствия для всего домена, поэтому редактировать значения атрибутов слудует с большой осторожностью.

Объект DirectorySearcher. Ещё одним важным объектом в пространстве имён System.DirectoryServices является объект DirectorySearcher, который позволяет производить поиск объектов в Active Directory. Создаётся объект таким образом:

DirectorySearcher DirSearch=new DirectorySearcher(rootEnt,strFilter);

Где rootEnt - объект типа DirectoryEntry контейнер от которого начинается поиск.

strFilter - строка фильтра в формате LDAP, например "(objectClass=user)".

По умолчанию используется фильтр "(objectClass=*)", который производит поиск всех объектов каталога. Выражение может включать операторы <, <=, =, >=, и >. Например “(lastName>=Ivan)". Комплексные выражения могут быть использованы с операторами & и |. Например

"(&(objectClass=printer)(|(building=42)(building=43)))".
Если фильтр содержит атрибут типа ADS_UTC_TIME, то его значение должно быть вида yymmddhhmmssZ, т.е. время вида "10:20:00 A.M. May 13, 1999" будет выглядеть так: “990513102000Z". Стоит также запомнить, что Active Directory сотраняет дату GMT. Поэтому если вам необходимо найти в Active Directory местное время, то вы можете использовать в фильтре формат “yymmddhhmmss [+/-} hhmm”, к примеру время "8:52:58 P.M. March 23, 1999" для Москвы будет выглядеть так "19990323205258.0+0300".

После того как объект DirectorySearcher создан, можно начинать поиск. DirectorySearcher имеет два метода для поиска объектов Active Directory. Это методы FindAll и FindOne. Метод FindAll возвращает коллекцию System.Directoryservices.SearchResult, т.е. возвращает все найденные объекты типа System.DirectoryServices.SearchResult, а метод FindOne возвращает первое найденное значение.

DirectorySearcher DirSearch=new DirectorySearcher(rootEnt, “(lastName>=Ivan)");

SearchResultCollection SearchResult=DirSearch.FindAll();
Получить объект типа DirectoryEntry из результатов поиска можно использовав метод GetDirectoryEntry(). Например, сохранить пути найденных объектов можно так:
ArrayList PathArr=new ArrayList();
foreach (SearchResult SearchRes in DirSearchResultCol)
	{
	PathArr.Add(SearchRes.GetDirectoryEntry().Path);
	}

Заключение

В этой статье мне хотелось паказать читателю, что работа с Active Directory не так сложна, как некоторым представляется. Как вы понимаете, я изложил лишь базовую часть возможностей пространства имём System.DirectoryServices, на самом деле возможности значительно шире. Для тех кто предполагает работать с Active Directory я бы порекомендовал литературу на сайте MSDN, а в частности следующие топики:

  1. Active Directory Programmers Guide
  2. Active Directory Service Interfaces
  3. Lightweight Directory Access Protocol API
  4. ADSI System Providers
  5. WinNT Binding String
  6. Binding
  7. IADsOpenDSObject::OpenDSObject
и конечно же документацию по .NET.


Может пригодится:


Автор: aspid
Прочитано: 21873
Рейтинг:
Оценить: 1 2 3 4 5

Комментарии: (0)

Добавить комментарий
Ваше имя*:
Ваш email:
URL Вашего сайта:
Ваш комментарий*:
Код безопастности*:

Рассылка новостей
Рейтинги
© 2007, Программирование Исходники.Ру