Asp объекты adsi


Содержание

Запрос свойства объекта Active Directory из приложения ASP.NET возвращает старые результаты

В течение довольно многих дней я пытаюсь использовать определенную аутентификацию на основе Active Directory. Все это работает теоретически, но, по-видимому, моя теория ошибочна. Пользователи, которые вошли в домен, записывают токен строки (например, PIN-код) в свое собственное поле свойств в Active Directory (на самом деле не важно, какой из них, но я использовал primaryInternationISDNNumber для этого) при входе в приложение ASP.NET Этот ПИН всегда генерируется и записывается программно.

Чтобы объяснить это примерно, веб-браузер загружает Java-апплет, который затем загружает собственную DLL, написанную в C++, которая генерирует и записывает ПИН-код в текущее поле Active Directory пользователя. Затем DLL возвращает сгенерированный PIN-код в апплет, который затем передает его в браузер, который выполняет вызов AJAX с данными, возвращаемыми для инициирования аутентификации. Приложение, получившее доступ к AD, считывает это значение поля для подключаемого объекта пользователя и проверяет, совпадает ли он с тем, который был предоставлен пользователем. Если совпадают PIN-коды, пользователь успешно аутентифицируется.

Это пример кода приложения ASP.NET, используемого для чтения AD:

Это работает нормально, часто. Но часто это неприемлемо. Он всегда должен работать.

Проблема в том, что приложение ASP.NET иногда получает значение, которое ранее было в этом поле, а не фактическое значение. Как будто есть какое-то кеширование. Я попытался добавить de.UsePropertyCache = false но это дало те же результаты.

Я создал два консольных приложения Win32 для тестирования. Один записывает PIN-код, другой считывает PIN-код. Они всегда отлично работают!

Я думал, это должно быть проблемой с пулом приложений IIS. Поэтому я создал родную DLL, которая загружается приложением ASP.NET с использованием Platform Invoke. Эта DLL создает новый поток, вызывает CoInitialize и считывает PIN-код. Это код:

К моему огромному и неприятному удивлению, этот код после дня правильной работы начал возвращать прежние значения, как и ранее управляемый код!

Итак, теперь я подумал, что я не смог избежать пула приложений IIS, и поскольку это должно быть проблемой с пулом приложений IIS, я создам собственное приложение Windows, которое я буду выполнять с помощью метода Process.Start. Я верну свой PIN-код с помощью кода выхода из процесса (так как это целое число). Приложение использует аналогичный C++ код в качестве DLL выше.

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

Но хорошо, я бы сказал, процесс запускается с использованием текущих учетных данных пользователя, который снова является пулом приложений IIS. Поэтому я запускаю приложение под разными учетными данными. И угадайте, что. он снова возвращает старое значение (. ).

И я думал, что Java — это ад. У кого-нибудь есть представление о том, что может происходить здесь?

Active Directory — теория построения

Архив номеров / 2004 / Выпуск №1 (14) / Active Directory — теория построения

ИВАН КОРОБКО

Active Directory – теория построения

В своей работе системному администратору часто приходится выполнять рутинные действия, которые отнимают много времени и требуют повышенного внимания. Управление Active Directory является одной из приоритетных задач системного администратора. Программное администрирование Active Directory позволит сэкономить время и свести к минимуму влияние человеческого фактора. Используя провайдеры LDAP и WinNT, системный администратор сможет с помощью сценария загрузки управлять подключением сетевых ресурсов; создавать скрипты, которые позволят автоматизировать рутинные операции. Умелое сочетание возможностей провайдеров WinNT и LDAP дает превосходный результат. Как показывает опыт, без теоретических знаний о механизме работы Active Directory и ADSI, базируясь на приведенных в Интернете примерах, очень трудно понять что к чему. В данной статье предпринята попытка поставить все точки над «и», не оторвав при этом теорию от практики (программирования Active Directory).

Программное управление с помощью VBScript

Как отмечалось ранее, для управления ADSI могут быть использованы VB/VBScript, JScript, C/C++. Для программного управления – компьютером, выполняющим роль контроллера домена, на котором установлена Active Directory, следует использовать стандартные средства, предлагаемые компанией Microsoft. Одним из таких стандартных средств является VBScript. Использование этого языка программирования дает огромные преимущества. Скрипты, написанные на VBScript помогут системному администратору не только управлять Active Directory, но и создавать сценарии загрузки для входа в сеть. По сравнению с С/С++, программный код на VBScript в несколько раз меньше, а по функциям равнозначен. Использование WHS (Windows Hosting Script) и WMI (Windows Management Instrument) совместно с программированием Active Directory позволит решать сложные задачи администрирования. И WSH, и WMI также являются стандартными средствами и поддерживают VBScript. Программирование WMI рассмотрено в статье «Решение задач инвентаризации в сети» в журнале «Системный администратор» №12(13) за 2003 год.

Использование VBScript позволяет создавать скрипты – текстовые файлы с расширением VBS, которые используются как сценарии загрузки при регистрации пользователей в сети, в виде сайтов на основе ASP. ASP-страница является синтезом HTML и VBScript. В отличие от HTML-страниц, ASP-страницы поддерживают OLE-объекты. Это позволяет использовать в ASP-страницах программирование WMI, WSH, ADSI.

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

Используя в скриптах массивы для передачи данных, при определении массива задавайте заведомо большее количество элементов в массиве, чем это необходимо, например Array(1000). После занесения данных в массив переопределите размер массива с помощью функции ReDim Preserve Array(i), где i – новый размер массива. При использовании цикла For определяйте границы массивов с помощью функций Lbound(Array) – нижняя граница массива, Ubound(Array) – верхняя граница (см. Пример 1а). Существует второй способ работы с массивами, который в основном используется в программировании ADSI – использование конструкции FOR EACH element IN array (см. Пример 1б).

Пример 1а Пример 1б

i= Lbound(Array) For Each i in Array

For i To Ubound(Array) element=Array(i)

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

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

For j=0 to Ubound(Array)

For i=0 to Ubound(Array)

If StrComp(Array_sort(i),Array_sort(i+1),0)=1 Then

Осуществление процедуры поиска в независимости от регистра символов является задачей, решать которую приходится очень часто. Для обеспечения процедуры поиска формируется массив, среди элементов которого происходит поиск. Для того чтобы сделать функцию поиска нечувствительной к регистру символов, необходимо использовать функцию, преобразующую все символы строки в большие или в маленькие. Это касается как элементов массива, так и искомой строки. Для преобразования строки в маленькие буквы используют функцию Lcase(string), для преобразования в большие – Ucase(string).

For i=0 to Ubound(Array)

if Instr(Lcase(Array(i)),LCase(SearchString)) then

MsgBox «Строка найдена»

MsgBox «Строка не найдена»

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

Active Directory обладает следующими особенностями:

  • Масштабируемость. В отличие от большинства других баз данных, которые являются реляционными, база данных Active Directory является иерархической. В базах данных взаимосвязи между записями определяются при помощи ключей, которые хранятся совместно с данными. В иерархической базе данных взаимосвязи между записями имеют характер «родитель-потомок»: каждая запись, за исключением корневой, обладает родительской записью. У каждой родительской записи может быть один или несколько потомков. Иерархическая база данных позволяет хранить большое количество объектов, при этом быстро получать доступ к необходимым объектам.
  • Поддержка открытых стандартов. Active Directory объединяет в себе концепцию пространства имен интернета со службой каталогов Windows NT, что позволяет объединить и управлять различными пространствами имен в разноразрядных аппаратных и программных средах. Для управления пространством имен Active Directory используется библиотека интерфейса службы активного каталога (Active Directory Service Interface – ADSI).
  • Поддержка стандартных форматов имен. Active Directory поддерживает несколько общих форматов имен. Этот факт позволяет приложениям и пользователям получать доступ к каталогу, применяя наиболее удобный для них формат:
Рубрика: Карьера/Образование / Образование
Формат Описание
UPN Формат основного имя пользователя (User Principial Name, UPN) описан в RFC 822. UPN известны как адреса электронной почты. AD обеспечивает «дружественные» имена в этом формате, таким образом, в качестве имя для входа в сеть пользователь может использовать как имя учетной записи SAM, так и имя в формате RFC 822, например NIvanov@company.com
LDAP URL Имена LDAP (см. RFC 1779, 2247), имеющие более сложную структуру по сравнению с URL именами, которые построены на основе протокола X.500. Имена URL LDAP состоят из следующих частей: CN, OU, DN.

CN расшифровывается как Common Name (общее имя), OU означает организационную единицу (Organization Unit) и DN означает контроллер домена (Distinguished Nаme – отличительное имя). Часть отличительного имени «DC=» делает возможным подключения каталогов X.500 к пространству имен DNS.

Пример, LDAP://www.domain.ru/CN=NIvanov, OU=Support, OU=Developers или LDAP:// CN=NIvanov, OU=Support, OU=Developers, DN=ru, DN=domain, DN=www

UNC UNC или канонический вид (Active Directory Canonical Name, ADCN), который имеет стандартный вид computer.domain.com/folder1/subfolder2. В AD данный формат является путем в иерархической структуре к объекту (см. RFC 1123)

DNS и Active Directory

Для иерархического именования доменов и компьютеров в Active Directory используется система DNS, поэтому объекты доменов и компьютеров являются как частью иерархии доменов DNS, так и иерархией доменов Active Directory. Несмотря на то, что имена в обеих системах идентичны, они относятся к различным пространствам имен. Взаимодействие DNS-имен доменов и их IP-адресов в Active Directory реализовано в согласии с общепринятыми соглашениями об именовании в DNS.

Доменная система именования (Domain Name System, DNS) представляет собой базу данных, реализующую иерархическую систему именования для идентификации хостов. Основная функция DNS (см. RFC 1034 и RFC 1035) заключается в прямом и обратном разрешении имен компьютеров в IP-адреса.

База данных DNS – это древовидная структура, называемая пространством имен доменов (domain space name).

В Windows 2000 полное доменное имя (Fully Qualified Domain Name, FQDN) компьютера состоит из 2 частей:

  • Имя DNS-узла. Крайняя левая метка – это полноценное имя DNS-узла, идентифицирующее учетную запись компьютера, хранящуюся в Active Directory. Кроме того, это имя локальной учетной записи компьютера в диспетчере безопасности учетных записей (Security Account Manager, SAM) на рабочей станции или рядовом сервере (не контроллер домена). По умолчанию имя DNS-узла также используется в качестве NetBIOS-имени. Это делается для совместимости с доменами на основе Windows NT 3.51 и Windows NT 4, а также для совместимости с рабочими станциями под управлением 9х.
  • Основное имя DNS-имени домена. По умолчанию – это домен Windows, к которому относится данный компьютер (см. рис. 1).

Рисунок 1. Порядок построения имен FQDN

Кроме DNS-имен компьютеров, контроллеры домена Active Directory идентифицируются по видам предоставляемых ими служб: серверы протокола LDAP (Lightweight Directory Access Protocol); контроллеры доменов; сервер глобального каталога GC (Global Catalog). Получив указание на имя домена и службу, сервер DNS способен найти контроллер со службой искомого типа в данном домене.

Глобальный каталог (Global Catalog, GC) – это контроллер домена, в котором существуют три доступных для записи каталога: домена, схемы и конфигурации. Каталог автоматически создается при репликации Active Directory. Все разделы каталогов на сервере глобального каталога хранятся в одной базе данных каталога (Ntds.dit). Глобальный каталог хранит сведения обо всех лесах, поэтому его можно использовать для поиска любых объектов в лесу без переадресации на другие серверы. Если запрос на поиск послан по порту 389 (стандартный порт протокола LDAP), то в случае неудачного поиска запрос будет последовательно передаваться другим контроллерам домена. В том случае, если обращение идет по стандартному порту глобального каталога (GC) 3268, поиск ведется по всем разделам леса. Для безопасного доступа к службам следует использовать порты, использующие SSL:

Порт Описание
389 Порт для открытых запросов LDAP
636 Порт для запросов LDAP c использованием протокола SSL
3268 Порт для открытых запросов GC
3269 Порт для запросов GC c использованием протокола SSL

Set gc = GetObject(«GC:»)

For each child in gc

Архитектура службы каталогов Active Directory

Чтобы понять, как хранятся и обрабатываются данные в Active Directory, необходимо представлять себе, как взаимодействуют отдельные компоненты этой службы каталогов. Службу каталогов можно представить в виде многоуровневой структуры. Существует три уровня служб и несколько интерфейсов и протоколов, которые образуют полный спектр служб каталогов (см. рис. 2). Три уровня служб содержат все данные для нахождения записей в базе данных каталога. Выше уровня служб находятся протоколы и API-интерфейсы, которые обеспечивают взаимодействие между клиентами и службами каталогов или при репликации – между службами каталогами.

Рисунок 3. Архитектура служб Active Directory

Далее перечислены основные службы-компоненты Active Directory:

  • агент системы каталогов (directory system agent, DSA) формирует иерархию каталога на основе отношений родитель-потомок и обеспечивает интерфейс прикладного программирования (application programming interfece, API) для запросов на доступ к каталогу;
  • уровень базы данных является промежуточным уровнем – уровнем абстракций между базой данных и приложениями;
  • ядро базы данных (Extensible Storage Engine, ESE), работающее непосредственно с записями хранилища каталогов, различает объекты по атрибуту относительно составного каталога.
  • хранилище данных (файл базы данных Ntds.dit). С этим файлом может работать только ядро базы данных. Обращаться напрямую к этому файлу можно только с помощью программы Ntdsutil, которая находится в папке Support/Tools на диске с операционной системой Windows 2000 Server.

Клиенты получают доступ к Active Directory по одному из перечисленных механизмов:

  1. LDAP/ADSI. Клиенты, поддерживающие протокол LDAP, используют его для доступа к агенту системы каталогов. Интерфейсы службы каталогов Active Directory (Active Directory Service Interface – ADSI) служат для абстрагирования от LDAP интерфейса прикладного программирования (API), представляя COM-интерфейсы для взаимодействия с Active Directory. Однако нужно помнить, что в Active Directory используется только LDAP;
  2. MAPI. При обмене сообщениями и коллективной работе клиенты MS Outlook подключаются к агенту системы каталогов по механизму вызова удаленных процедур MAPI через интерфейс средства доступа к адресной книге.
  3. SAM. Клиенты MS Windows NT 4.0 и ранее Windows 9x подключаются к агенту системы каталогов (DSA) через SAM;
  4. REPL. В процессе репликации каталогов агент системы каталогов (DSA) Active Directory взаимодействует через RPC-интерфейс.

Объектная модель ADSI

Наглядная схема объектной модели ADSI приведена на рисунке.

Рисунок 4. Объектная модель ADSI

Схема условно поделена на три части. Используя клиента – язык программирования, скрипт получает доступ к COM-объектам. Объекты могут быть двух видов – классы и подклассы. Обращение к подклассам осуществляется через классы, однако на схеме это не показано, чтобы не загромождать рисунок. С помощью COM-объекта через протокол LDAP или WinNT сценарий загрузки получает доступ к выбранному элементу объектной модели. Пространство имен условно обозначено треугольником; квадратами обозначены классы, а кружками – подклассы. Методы доступа к каждому из перечисленных протоколов отличаются, однако можно привести пример, который наглядно демонстрирует приведенную схему:

For each SubClass in ClassName

Интерфейс ADSI поддерживает следующие провайдеры, с помощью которых осуществляется программное администрирование:

Название Протокол Описание
LDAP Provider «LDAP:» Администрирование Active Directory, Microsoft Exchange Server
WinNT Provide «WinNT:» Администрирование Windows NT, Windows 200x, Windows XP
NDS Provider «NDS:» Администрирование Novell NetWare Directory Service
NVCOMPAT «NVCOMPAT:» Администрирование Novell NetWare 3.1
IIS «IIS: Протокол IIS предназначен для управления WWW и FTP узлами по протоколу HTTP

Для определения всех доступных протоколов на вашем компьютере необходимо использовать службу ADS:

For Each provider IN obj

temp = temp + provider.name + chr(13)

Из всех перечисленных провайдеров будут рассмотрены только LDAP и WINNT.

Провайдер ADSI LDAP выполняется на клиенте ADSI и обеспечивает доступ к Active Directory.

Кроме служб каталогов Active Directory Windows 2000, LDAP-провайдер обеспечивает доступ к:

  • Netscape Directory Server;
  • Microsoft Exchange Server 5.x и выше;
  • Microsoft Commercial Internet System (MCIS) Address Book Server.

Программное управление Active Directory часто используется именно этим провайдером. Запрос провайдеру LDAP составляется в формате LDAP URL (см. RFC 1779, RFC 2247):

Провайдер WinNT ADSI поддерживает доступ к каталогам Microsoft Window 4.0/3.x, обеспечивает связь с PDC и BDC. Провайдер WinNT в основном используется для работы с принтерами. Причина проста: в отличие от провайдера LDAP провайдер WinNT рассматривает принтер не как сетевое, а как локальное устройство. Только с помощью провайдера WinNT можно управлять состоянием и очередями принтеров. Совместное использование обоих провайдеров позволит осуществлять мониторинг и управление сетевыми принтерами домена (см. статью «Управление сетевыми принтерами» в журнале «Системный администратор» №10(11) за 2003 г.). Порядок построения запроса для провайдера WinNT в формате UNC следующий:

Получив фундаментальные знания о построении Active Directory, поддерживаемых форматов имен и провайдером, принципах программирования скриптов, можно приступать к изучению объектных моделей провайдером. Как ни странно, даже исчерпывающие знания объектной модели, умение применять на практике различные методы, обеспечиваемые провайдерами, не позволяют успешно программировать ADSI. По собственному опыту могу сказать, что не зная основы (теории), которая сначала кажется лишней, невозможно добиться корректной работы скрипта в 100% случаях. Приведу один маленький, но очень наглядный пример: в статье «Управление сетевыми принтерами» в журнале «Системный администратор» №10 за 2003 г. рассказано о том, как с помощью небольшого сайта, написанном на ASP, управлять сетевыми принтерами домена. Не секрет, что сначала создаются наработки – небольшие сценарии, затем состыковывая эти небольшие отрывки между собой, получают решение какой-либо задачи. Заготовки были написаны на VBS, а сайт написан на ASP, который хоть и поддерживает VBS, все же накладывает свой отпечаток. После завершения создания сайта было замечено, что он довольно часто выдает ошибку связанную с тем, что невозможно найти базу, хотя все отрывки на VBS были оттестированы и признаны работающими корректно. Сначала грешили на репликацию двух контроллеров домена. Однако, оказалось, что проблема была в том, что имя сервера печати в провайдере LDAP необходимо было указывать в полном формате, т.е. не server, а server.domain.com. Несмотря на то, что VBS к формату имени равнодушен, для ASP это оказалось принципиальным. Посмотрите таблицу 1 и сразу станет ясно какой формат имен необходимо использовать.

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

ASP использование GetObject для вызова методов ADSI

У меня есть классический ASP-сайт, работающий под контекстом пула приложений учетной записи домена,который использует Windows-auth для проверки переднего плана. Код может запрашивать AD через LDAP и ADSI просто отлично, однако при попытке получить ссылку на объект, похожий на объект компьютера, используя GetObject, он не может сделать этого. Я читал это [http://support.microsoft.com/kb/278836] но я смущен тем, почему он, похоже, не работает в контексте пула приложений, когда учетная запись (a) пользователь домена и (b) имеет разрешения на выполнение действий (перемещение компьютера из одного подразделения в другое подразделение). Есть ли другой способ заставить его работать без перезаписи сайта ASP.NET или что-то вроде этого?

1 ответ

Не берите в голову. Я понял, что лучший вариант для этой конкретной задачи состоит в том, чтобы поставить запрошенную операцию в очередь в таблице базы данных и обработать ее с помощью отдельной запланированной задачи. Это позволяет записывать как запрос, так и результат завершения процесса.

ASP using GetObject to invoke ADSI methods

I have a classic ASP site running under a domain account application pool context, which is using windows-auth for the front end user validation. The code is able to query AD via LDAP and ADSI just fine, however when trying to obtain an object reference to something like a computer object using GetObject, it is unable to do so. I read this [http://support.microsoft.com/kb/278836] but I’m confused about why it doesn’t seem to work under the application pool context when the account is (a) a domain user, and (b) has permissions to perform the actions (move computer from one OU to another OU). Is there another way to make it work without rewriting the site in ASP.NET or something like that?

1 Answer 1

Never mind. I realized that a better option for this particular task is to queue up the requested operation in a database table and process it using a separate, scheduled task. That allows for recording both the request and the result of the process completion.

Not the answer you’re looking for? Browse other questions tagged asp-classic com ldap adsi or ask your own question.

Hot Network Questions

Subscribe to RSS

To subscribe to this RSS feed, copy and paste this URL into your RSS reader.

site design / logo © 2020 Stack Exchange Inc; user contributions licensed under cc by-sa 4.0 with attribution required. rev 2020.11.11.35402

Сценарии для Active Directory. Часть 1

Многие системные администраторы Windows 2000 и Windows NT убедились, что разработка обычных сценариев для управления инфраструктурой принципиально отличается от использования традиционных графических инструментальных средств. Тем, кто придерживается такой точки зрения, я советую изучить технологию Windows Script (WS) и сопутствующие ей, в частности Active Directory Service Interfaces (ADSI). Писать пользовательские сценарии для управления средой не требуется, а создавать сценарии для Active Directory (AD), позволяющие осуществлять администрирование, становится намного проще. В этой статье я расскажу о трех основных интерфейсах в ADSI (IADsOpenDSObject, IADs и IADsContainer) и покажу, каким образом, используя эти основные интерфейсы, можно выполнить более 80% обычных задач управления AD.

Что такое ADSI?

Интерфейс ADSI — это набор COM-объектов для программирования, которые позволяют единообразно манипулировать многочисленными гетерогенными каталогами. Интерфейс ADSI — это основной программный интерфейс к AD, разработанный Microsoft, его используют все графические средства управления AD.

Изначально ADSI поддерживал протоколы Lightweight Directory Access Protocol version 3 (LDAPv3), NT 4.0 SAM, Novell Directory Services (NDS) и NetWare Bindery. Поскольку ADSI поддерживает LDAP, он может использоваться для управления каталогами, основанными на LDAP/X.500, включая Windows 2000 AD, Microsoft Exchange Server 5.5 и Site Server 3.0. Хотя я буду рассматривать именно AD, многие принципы, обсуждаемые в этой статье, применимы и к другим каталогам.

Так как интерфейс ADSI предназначен для программирования, его можно применять для написания сценариев управления каталогом в любой COM-совместимой среде, включая Windows Script Host (WSH), VBScript, JScript и ActivePerl. Интерфейс ADSI также поддерживает быстродействующие, только для чтения, запросы ActiveX Data Objects (ADO) через OLE DB.

ADSI устанавливает интерфейсы на стороне клиента. Это означает, что инсталлировать его нужно только на тот компьютер, который запускает сценарии. Дополнительно устанавливать ADSI на целевые контроллеры домена не требуется. Система Win-dows 2000 включает ADSI, но если планируется запускать сценарии ADSI на компьютерах с Windows NT или Windows 9x, то его необходимо загрузить и установить. ADSI 2.5 — это текущая версия, которую можно загрузить с Web-сайта Microsoft по ADSI (http://www.microsoft.com/adsi). На сайте также размещены связанные с ADSI официальные документы и средства для разработчиков, например набор инструментальных средств разработки для ADSI (SDK).

Терминология AD и ADSI

Чтобы эффективно использовать ADSI, необходимо изучить терминологию сценариев AD.

AD — это служба каталогов (DS) Win-dows 2000. DS — сетевая служба, которая идентифицирует и хранит информацию обо всех сетевых ресурсах и обеспечивает пользователям и приложениям доступ к ней. Служба каталогов AD — это распределенный иерархический тиражируемый каталог информации (Distributed information tree, DIT), который хранится в каталоге \%systemroot% tds на всех контроллерах домена Windows 2000 в фaйле ntds.dit. Можно обновить любую копию AD, и изменения AD будут тиражироваться на все контроллеры домена.

Служба каталогов AD в чем-то сходна с базой данных (например, AD тоже хранит информацию). Однако, в отличие от реляционных баз данных, которые предназначены для выполнения операций вставки, обновления и удаления, AD — это иерархическая структура, оптимизированная для операций чтения.

Каждый контроллер домена Windows 2000 поддерживает доступную для записи копию каталога (реплику), и каждая реплика состоит как минимум из трех разделов (известных как контексты именования): контекста именования по умолчанию, контекста именования схемы и контекста именования конфигурации. Контекст именования по умолчанию хранит информацию об общих объектах домена (таких, как компьютеры, группы, организационные единицы (OU), пользователи). Контекст именования схемы хранит схему AD (которая будет описана ниже), а контекст именования конфигурации хранит информацию о конфигурации узла и подсети. Основные интерфейсы обеспечивают общий и постоянный доступ к управляемым объектам во всех трех контекстах именования.

Компонент «схема» — это коллекция описаний классов и атрибутов; она определяет, какую информацию может хранить AD. Класс подобен шаблону для объекта, а атрибут — это свойство объекта (например, общее имя, описание, отличительное имя (DN)). Схема описывает обязательные и дополнительные атрибуты объекта. В рамках ADSI-сценариев можно получить доступ к схеме для установки обязательных и дополнительных свойств объектов. Кроме того, схема определяет структуру дерева каталога DIT. Объекты, которые могут содержать другие объекты, называются контейнерами; объекты, которые не могут содержать другие объекты, называются листьями.

Служба каталогов AD представляет сетевые ресурсы как объекты. С точки зрения AD объект есть заданный именованный набор свойств и связанных с ними значений, которые представляют конкретные сетевые ресурсы (например, компьютер, названный US-E-FN-01; группа, имеющая имя Investors, организационное подразделение OU с именем Finance, пользователь Джуди). С точки зрения программы или сценария объект есть экземпляр класса схемы.

Интерфейсы в ADSI являются механизмами, которые используются для модификации свойств объектов. Термин «интерфейс» — не единственный в ADSI. В программировании COM-интерфейс — это набор методов и свойств, которые предоставляет COM-объект. Методы оказывают некоторое воздействие на объект, а свойства характеризуют состояние объекта. Объекты COM могут предоставлять разнообразные интерфейсы. Например, ADSI обеспечивает более 50 интерфейсов. Однако всего три базовых интерфейса позволят выполнить многие задачи в AD.

Таким образом, ADSI — это набор программных интерфейсов, который используется для управления объектами AD. Интерфейсы ADSI обеспечивают методы и свойства для создания, удаления и модификации объектов. Объект есть набор свойств, которые представляет сетевой ресурс. Описание класса объекта, которое хранит схема, определяет свойства, создающие объект. Схема класса определяет обязательные и дополнительные атрибуты объекта. Сценарий ADSI использует методы ADSI для создания и удаления объектов и модификации свойств.

Каждый объект в AD имеет несколько имен. Отличительное имя DN и относительное отличительное имя (RDN) являются основными в соглашении об именовании для обращения к объектам из сценариев ADSI. Имя DN определяет точное расположение объекта в дереве DIT, основанном на именах атрибутов. Имя RDN — это обязательный атрибут «имя» объекта. Соотношение между именами DN и RDN в AD подобно соотношению между полностью определенным путем к файлу и именем файла в файловой системе.

Каждый DN-компонент есть RDN, а каждый RDN есть строка, состоящая из двух частей (параметр и значение), которая изображается как «key=va-lue». Key идентифицирует реальный тип атрибута, а value является значением атрибута.

В документе Internet Engineering Task Force (IETF) Request for Comments (RFC) 2253, «Lightweight Directory Access Protocol (v.3): UTF-8 String Representation of Distinguished Na-mes», описаны параметры и типы атрибутов, которые используются для создания имен DN в LDAPv3. В Таблице 1 перечислены некоторые из обычно применяемых параметров и соответствующие типы атрибутов.

Приведу пример связи между DN и RDN. На Рисунке 1 показаны DN и RDN для пользователя Джуди Шнайдер. RDN для Джуди — это «cn=Judy Schneider»; cn — это параметр для общего имени атрибута, а строка «Judy Schneider» является значением. Мы можем проверить имя DN Джуди, чтобы определить его точное месторасположение в DIT. Джуди входит в подразделение Finance OU, а то, в свою очередь, относится к домену acme.com. Можно представить DN как комбинацию всех объектов RDN при перемещении от объекта к корню дерева.

Рисунок 1. Имена DN и RDN.

Имя DN объекта должно быть уникальным во всем каталоге, а RDN объекта должно быть уникальным в текущем контейнере. Параметр и знак равенства — это обязательные компоненты RDN. Типы объектов, которые не имеют конкретного параметра, используют по умолчанию общее имя параметра «cn=».

Общие задачи AD

Три базовых интерфейса ADSI можно использовать для создания, модификации и удаления почти любого объекта AD (например, учетной записи пользователя, учетной записи компьютера, группы, OU, сайта, подсети). Можно просматривать контейнеры и создавать настраиваемые отчеты так же, как добавлять новые классы и атрибуты для расширения схемы.

Процесс написания любого ADSI-сценария включает несколько основных этапов. В следующем сценарии я перечислил действия, необходимые для создания объекта «пользователь» и управления им.

Компания Acme Widgets приглашает Джуди Шнайдер на работу в качестве инспектора. Джуди будет работать в финансовом подразделении компании — Finance OU. Вместе с системным администратором Acme Widgets совершим четыре шага для создания нового пользователя.

  1. Используя функцию GetObject VBScript, подсоединимся к целевому контейнеру («ou=Finance» в этом примере), который будет содержать нового пользователя.
  2. Используя метод Create из ADSI, создадим новый объект «пользователь» в локальном кэше свойств. Интерфейс IADsContainer предоставляет метод Create.
  3. Используя методы Put и PutEx из ADSI, установим обязательные и дополнительные свойства объекта «новый пользователь». Интерфейс IADs обеспечивает методы Put и PutEx.
  4. С помощью метода SetInfo из ADSI запишем новый объект в каталог. SetInfo также является частью интерфейса IADs.

Джуди покупает новый дом и переезжает. Необходимо обновить ее домашний адрес и номер домашнего телефона, поэтому выполняем следующие действия.

Джуди выдвигается на пост финансового директора компании (CFO). Необходимо перевести Джуди из финансового подразделения (Finance OU) в руководство (Executive OU), для этого выполняем два шага.

Джуди переходит к конкуренту. Необходимо удалить объект пользователя, поэтому выполним два последних шага.

  • Используя функцию GetObject из VBScript, подключаемся к целевому контейнеру («ou=Executive»), который содержит объект пользователя.
  • С помощью метода Delete из ADSI удаляем объект пользователя. Интерфейс IADsContainer предоставляет метод Delete.
  • В этом примере показаны основные шаги, которые являются общими для большинства сценариев ADSI. Приступая к выполнению каждой задачи, нужно подключиться к объекту. После подключения к объекту используются методы, содержащиеся в двух основных интерфейсах IADs и IADs-Container, с помощью которых и происходит управление жизненным циклом объекта.

    Эти основные шаги можно применять и к другим объектам в каталоге. Для этого нужно отвлечься от основных интерфейсов в ADSI и выполнить перечисленные шаги в сценарии на базе функций. Я использую easyadsi.vbs в качестве примера и исследую основной интерфейс IADsOpenDSObject. В Листинге 1 показана часть сценария, которая выполняет первые четыре шага для создания нового объекта пользователя. Полностью листинг можно загрузить с Web-сайта Win-dows 2000 Magazine по адресу: http://www.win2000mag.com/. (Введите 9168 в текстовом окне InstantDoc ID и загрузите файл 9168.zip.)

    Листинг 1. Файл Easyadsi.vbs.

    Подключение к AD

    Подключение — это первый шаг для взаимодействия с AD; соединение с объектом в LDAP называют запросом на привязку (bind request). Привязка — это точка в сценарии ADSI, в которой происходит процесс аутентификации. Внутренние LDAP-провайдеры интерфейса ADSI (adsldp.dll и wldap32.dll) создают и возвращают ссылку на указанный объект (например, домен, OU, группа, пользователь, принтер, служба, совместно используемый ресурс, сайт, класс схемы).

    Используем функцию GetObject из VBScript для привязывания к объекту AD. Строка, передаваемая в Get-Object, — это ADSI LDAP — путь, который идентифицирует целевой объект. Для связывания с объектом можно использовать несколько подходов, которые основаны на синтаксисе LDAP-пути. ADSI LDAP-путь необходимо начать с «LDAP:». Далее может следовать строка с дополнительными элементами, как показано в примере на Рисунке 2.

    Обязательный префикс «LDAP:» — это программный идентификатор (ProgID) для провайдера LDAP в ADSI. Идентификатор ADSI ProgIDs определяет ADSI провайдера DLL, через который сценарий поддерживает связь с каталогом. Идентификатор ADSI ProgIDs является чувствительным к регистру, поэтому для префикса «LDAP:» необходимо всегда использовать заглавные буквы. Остаток ADSI LDAP-пути нечувствителен к регистру.

    Дополнительные элементы LDAP-пути включают имя целевого сервера, IP-адрес, номер порта LDAP и DN. Элементы, добавляемые к префиксу «LDAP:», определяют, как ADSI привязывается к AD.

    Серверные привязки создаются при добавлении имени целевого сервера или IP-адреса как части LDAP-пути, что показано в примерах на Рисунке 3. Следует избегать привязок с явным указанием имени сервера или IP-адреса, потому что сценарий выдаст ошибку, если сервер окажется отключенным. Можно установить номер порта LDAP, если DS прослушивает другой порт, а не порт LDAP по умолчанию (порт 389). Однако не нужно беспокоиться о прослушивании AD по другому порту, потому что контроллеры домена Windows 2000 резервируют порт 389 для AD. Запросы без привязки к серверу удаляют зависимость, связанную с LDAP-путями, которые содержат явно указанные имена серверов. Поэтому целесообразнее использовать пути без имени сервера. Если не указать имя целевого сервера или его IP-адрес, ADSI выдает запрос к новому Win32 API (DSGetDCNa-me), который запрашивает DNS для поиска контроллера в домене, где зарегистрировался данный пользователь. Интерфейс ADSI пытается определить местоположение контроллера домена и подключиться к нему в локальном узле рабочей станции, основываясь на IP подсети. Если ADSI не может определить контроллер домена в узле, он использует первый ответивший сервер каталога.

    Пути LDAP без указания сервера обычно включают имя DN, которое идентифицирует целевой объект. В запросе на привязку, показанном в Листинге 1 под меткой А, я сделал привязку к Finance OU, которая находится в домене acme.com. Строковое значение в переменной strContainer указывает его местоположение.

    На Рисунке 4 показаны запросы на привязку, которые содержат другие виды путей LDAP без указания сервера. В первом примере на Рисунке 4 я выполнил привязку точно к de-faultNamingContext (где находятся объекты «пользователь», «компьютер», «группа» и OU) из домена acme.com. Во втором примере я сделал привязку к объекту конкретного пользователя. Третий пример является запросом на привязку без указания DN. При таком типе запроса ADSI создает привязку к специальному LDAPv3-объекту, Root Directory Ser-vice Entry (rootDSE), и использует свойство defaultNamingContext объекта rootDSE для привязки к корню DIT. Результат такой же, как и в первом примере, но использование запроса без указания DN снимает зависимость от специфики домена.

    Можно также явно сделать привязку к объекту rootDSE. Введенный в версии LDAPv3 rootDSE находится на вершине дерева DIT каждого контроллера домена. В отличие от принципа привязки без DN (например «LDAP:»), в котором rootDSE возвращает только имя DN для defaultNamingContext, привязка напрямую к rootDSE позволяет получить доступ ко всей информации о каталоге сервера, предоставившего объект rootDSE. В этой информации будут и имена DN для всех контекстов именования каталога. Как показано в Листинге 2, я использовал свойства defaultNa-mingContext, schemaNa-mingContext и configura-tionNamingContext объекта rootDSE, отмеченные как A, B и C, для привязки к корню каждого контекста именования каталога и просмотра высокоуровневых объектов.

    Листинг 2. Файл RootDSE.vbs.

    До сих пор я надеялся на имеющиеся у меня разрешения при проверке запроса на привязку. Хотя такой метод аутентификации достаточно эффективен, в некоторых случаях бывает необходимо указать другие учетные данные или соответствующий тип аутентификации. Интерфейс IADSOpenDSOb-ject из ADSI предоставляет для выполнения привязки к объекту метод OpenDSObject, который предполагает использование указанных пользователем учетных данных. Метод Open-DSObject допускает четыре параметра, которые перечислены в Таблице 2.

    В Листинге 1 показано, как использовать OpenDSObject вместо текущих учетных данных пользователя (метка B). Замените код с меткой A в Листинге 1 кодом с меткой B в Листинге 1 для использования Open-DSObject. Перед тем как обратиться к Open-DSObject, нужно ввести

    чтобы получить ссылку на провайдера LDAP. В качестве имени пользователя можно указать DN, User Principal Name (UPN), низкоуровневое учетное имя SAM (pre-Windows 2000) или Anonymous.

    Советы по привязкам

    Интерфейс ADSI обеспечивает большую гибкость при выполнении привязок к объектам AD. При разработке собственных ADSI-сценариев нужно иметь в виду следующее.

    1. Используйте текущие учетные данные всегда, когда это возможно.
    2. Никогда не применяйте явно указанные пароли в своих сценариях. При необходимости использовать пароль нужно создать запрос, адресованный пользователю, или извлечь пароль из системы безопасности. Затем следует сохранить его во временной переменной и уничтожить содержимое переменной сразу же после запроса на привязку.
    3. Используйте rootDSE, когда сценарий делает привязку к корню текущего домена.
    4. Избегайте явного указания имен серверов в путях LDAP.
    5. Делайте привязки к контейнерам для создания, перемещения и удаления объектов в контейнере.
    6. Делайте привязки к объектам-листьям для модификации свойств объекта.

    В следующей статье, посвященной ADSI, я планирую рассказать о двух других основных интерфейсах ADSI — IADs и IADsContainer. А пока рекомендую читателям попробовать привязаться к некоторым объектам в своем каталоге. Для большего эффекта советую включить Network Monitor и попытаться задействовать несколько методов привязки.

    БОБ УЭЛЛС — консультант по программному обеспечению; специализируется на вопросах проектирования и реализации инфраструктуры информационных систем, основанных на NT. Имеет сертификаты MCSE и MCT. С ним можно связаться по адресу: bobwells@win2000mag.com.

    Таблица 1. LDAPv3 DNs.

    Key Attribute Type
    CN commonName
    L localityName
    ST stateOrProvinceName
    O organizationName
    OU organizationalUnitName
    C countryName
    STREET streetAddress
    DC domainComponent
    UID userid

    Поделитесь материалом с коллегами и друзьями

    Asp объекты adsi

    Здравствуйте товарищи! Рад, что вы вновь заглянули на IT блог pyatilistnik.org. Я уже неоднократно вам рассказывал, о разных вещах посвященных активному каталогу (Active Directory), но так и не касался, довольно повседневной функциональности в виде редактора атрибутов AD. Сегодня я исправлю, этот недочет и мы с вами разберем. Что из себя представляет редактор атрибутов Active Directory, как его открыть, что он вам даст в вашей работе и как позволит эффективно его использовать. Думаю для многих инженеров или системных администраторов будет очень полезно, освежить знания в данной области.

    Что такое редактор атрибутов Active Directory

    И так ранее мы с вами установили Active Directory, и разобрались со всеми понятиями активного каталога, из которых мы выяснили, что администратор, получает информацию о всех объектах схемы в виде красивого графического интерфейса, например, оснастки ADUC, а вот контроллеры домена и другие компьютеры, получают информацию об объектах в виде языка LDAP, который лежит в основе Active Directory.

    В итоге можно дать вот такое определение редактору атрибутов Actvie Directory — это дополнительная надстройка в графической утилите управления объектами активного каталога, позволяющая в удобном для человека редакторе, внести изменения в нужные атрибуты схемы, а так же проверить и посмотреть остальные значения в неизменяемых атрибутах.

    Приведу простой пример использования редактора атрибутов:

    • Необходимо узнать distinguished name
    • Задать automapping для почты пользователю с правами только на чтение

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

    Как открыть редактор атрибутов Active Directory

    Для того, чтобы открыть редактор атрибутов, можно воспользоваться четыремя методами:

    • использование оснастки Active Directory пользователи и компьютеры
    • использование Active Directory Administrative Center
    • использование ADSI Edit редактора
    • использование оболочки powershell

    Ниже я хочу подробно рассмотреть, где и как редактировать атрибуты в данных инструментах.

    Просмотр и редактирование атрибутов Active Directory в оснастке ADUC

    Заходим в меню «Пуск», в котором находим пункт «Active Directory Пользователи и компьютеры» либо откройте окно «Выполнить» и введите служебное название dsa.msc. (Полный список названий служебных сокращений Windows, читайте по ссылке слева)

    У вас откроется ADUC. Если вы зайдет в свойства любой учетной записи, в моем примере это Барбоскин Геннадий, то обнаружите, что редактор атрибутов в списке вкладок отсутствует. Чтобы его отобразить сделайте следующие действия.

    Открываете вкладку «Вид», в меню находите пункт «Дополнительные компоненты», включаем его.

    После чего, вкладка редактора атрибутов отобразиться в свойствах учетной записи объекта Active Directory.

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

    • CN (Common Name) — Отображаемое имя
    • LastLogon — время логирования
    • Discription — Описание

    В момент изменения будет открыт редактор строковых или целочисленных атрибутов.

    По умолчанию Active Directory в редакторе атрибутов, отображает, только атрибуты со значениями, то есть не пустые. Для того, чтобы увидеть все атрибуты, вам необходимо применить фильтр, через соответствующую кнопку. Снимите галку «Отображать только атрибуты со значениями». Так же можно более тонко настроить фильтрацию и задать, например, показывать, только атрибуты доступные для записи (изменения вручную) или только системные. Я вам советую посмотреть все варианты и проверить, что каждый из них отображает. Переходим к ADSI Edit.

    Редактирование атрибутов Active Directory в ADSI Edit

    Напомню, что ADSI Edit — это служебная оснастка, которая позволяет подключаться к различным разделам базы данных Active Directory (Ntds.dit). Открыть «Редактор ADSI», можно также из меню «Пуск» на контроллере домена, либо так же через окно «Выполнить» (Сочетание клавиш WIN и R). Введите adsiedit.msc.

    Далее в оснастке, кликните правым кликом по «Редактирование ADSI» и выберите «Подключение к»

    Для того, чтобы зайти в редактор атрибутов, выберите пункт «Выберите известный контекст именования». Подключаемся к стандартному, идущему по умолчанию.

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

    Вы попадете на вкладку «Редактор атрибутов», который мы с вами уже видели в оснастке «Пользователи и компьютеры». Можете производить редактирования. Перейдем к третьему методу, использование Active Directory Administrative Center.

    Редактирование атрибутов Active Directory в Центр администрирования Active Directory

    Третий метод просмотра атрибутов у объектов AD, заключается в использовании оснастки «Центр администрирования Active Directory» (Active Directory Administrative Center). Открываем его через пуск или набрав команду в окне «Выполнить» dsac.exe.

    Если кто-то не в курсе, то Центр администрирования Active Directory — это оснастка построенная на оболочке power shell, все что вы тут выполняете, делается в фоновом режиме именно этим языком, плюс вы всегда на выходе графических манипуляций, получите полную команду, как это делалось бы в power shell. Переходим в нужное расположение объекта.

    Открываем его свойства, переходим на вкладку «Расширения» и перед вами будет, знакомый редактор атрибутов AD. Вот так вот его запрятали. Хочу отметить, что начиная с Windows Server 2012 R2, компания Microsoft старается продвигать все работы с объектами Active Directory именно в этой утилите и оснастке power shell и это понятно, у последнего возможностей в разы больше, чем у GUI собратьев. Поэтому, кто еще пока с ним не знаком, будет очень полезно начать именно с оснастки «Центр администрирования Active Directory», которая имеет подсказки, как все сделать через оболочку power shell.

    Редактирование атрибутов Active Directory в Power Shell

    На текущий момент самой актуальной версией power shell является 5-я, и компания Microsoft каждый год расширяет возможности данного языка на несколько сотен командлетов, помогая автоматизировать все, что вы хотите и удовлетворить потребности людей любящих операционные системы семейства Linux, например, CentOS. Чтобы посмотреть атрибуты пользователя, нам поможет командлет Get-ADUser и для того, чтобы изменить атрибут Set-ADUser.

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

    Вводим команду: Import-Module activedirectory. После чего запросим информацию о пользователе Барбоскине.

    Как видите атрибутов Active Directory не так много вывелось, добавим ключик -Properties *

    В итоге вывод оказался очень информативным.

    Более подробно про вывод командлета Get-ADUser читайте на сайте Microsoft. Теперь давайте изменим, например, для пользователя Барбоскин его домашнюю страницу, для этого пишем:

    Set-ADUser -Identity barboskin.g -HomePage ‘http://pyatilistnik.org’

    Как видите операционная система Windows позволяет вам редактировать и взаимодействовать с редактором атрибутов Active Directory разными методами, каждый вы будите использовать в разных ситуациях, для единичных изменений, вероятнее всего ADUC, для автоматизации, это будет несомненно power shell. Наверняка, есть еще и сторонний софт, но зачем он нужен, когда все идет из коробки.

    Asp объекты adsi

    Using ADSI in Delphi


    • Binding
    • Accessing Properties
    • Searching
    • Using ADO
    • Using IDirectorySearch Security

    ADSI Schema
    Providers
    Conclusion

    Introduction

    Microsoft has released Active Directory Service Interfaces (ADSI) for Windows 9x, NT and Windows 2000, and now it’s inbuilt in Windows 2000. The Windows 2000 application specification states that you must use Active Directory when you can, so now you’re thinking: How are YOUR applications going to adapt? What changes do you need to make? How are you going to use Delphi effectively to make these changes? This is what I intend to address in this presentation.

    Let me first introduce a “directory service”. A directory service is like a telephone directory: if you have a person’s name, you can find his/her phone number. A directory service keeps track of “resources”, which could be anything – a file system is a directory that keeps track of files and folders, an email server is a directory service that indexes users, user groups etc. There are many directory services already in place: we already have file systems and email servers. What’s so different? Traditionally, you’d have to use different API’s (Application Programming Interfaces) to access different directory services – which :

    1. Limit you to the vendor’s directory service. For example, if you wrote an application that extracted email information from Microsoft Mail and used the Mail Application Programmers Interface (MAPI), you would find it difficult to move to a different vendor.
    2. Increase development time for your applications because you need to learn more API’s to get your application working.

    There is a need to have a common model that every directory service would support – similar to the ODBC programming model that all (or most) database vendors now support. A model that will support a hierarchy of resources, like folders and files, and be simple to use. Active Directory provides this model. To access an Active Directory, you will use Active Directory Service Interfaces(ADSI).

    Where is Active Directory used?
    «Active Directory» encapsulates all directory services — a list of printers on a network, a set of services on an NT server etc. Directory services are very useful in an enterprise where one might know what he wants, may not know what that resource is named. (like, «give me a list of printers in the 2nd floor»).
    Any directory service can choose to publish itself as an Active Directory, so that a common querying mechanism can be used. At this point the following products support Active Directory:

    1. Microsoft Exchange Server: Allows queries for email ids, names and a number of other attributes of people or groups across an enterprise.
    2. Microsoft Site Server: Stores the list of users as an Active Directory.
    3. Microsoft Windows NT: This gives you uniform access to users (earlier through User Manager for Domains), services (earlier through service manager) and network resources (computers, printers etc.)

    Active Directory also provides bridges to access other similar directory services, like LDAP, NDS (Novell Directory Services) etc.

    Active Directory is also an integral part of Windows 2000. In a large organization, Windows NT server has been used as a Primary or Backup Domain Controller, but it was difficult to integrate many such controllers to be able to provide security and privileges across the organization. Active Directory makes it simpler by allowing you to structure your organization into units which seamlessly (or so they say) integrate with each other. Which also means lesser problems when you expand, add more servers, more users etc.

    To know more about how you can use Active Directory effectively in your organization, please visit: http://www.microsoft.com/windows2000/library/technologies/activedirectory/default.asp

    Here’s a list of places ADSI would be best used in:

    1. User/Groups:Adding/Deleting users , Finding out if a user is a member of a group.
    2. Changing a user’s password
    3. Starting and stopping services.
    4. Getting printer information (jobs in print queue etc.)
    5. Adding/Deleting web or FTP sites from Microsoft Internet Information server.
    6. Getting user attributes from Microsoft Exchange Server, like email ids, Addresses, web directories etc.

    These are just a few applications, and I’m sure there will be more as time goes on.

    Prerequisites – What do you need to know?

    This presentation assumes readers know COM (Component Object Model) and a working knowledge of using COM in Delphi.

    What is ADSI?

    Directory Services and Namespaces
    There could be many objects within a namespace (users in an email server, files in a file system) which need to be uniquely identifiable by name. But you might have a user in the email server with the same name as a file in the file system:and they have no idea about each others existance. To maintain uniqueness, object names are prefixed with the name of the Directory Service they belong to. This name identifies a «namespace», with a namespace identifier like «WinNT:», «LDAP:» etc. (The «:» means that it’s a namespace, and therefore, a directory service)

    Object names are prefixed by the namespace identifier, and «//».
    Note:This has analogies in the Internet, where you’d have Web pages identified by «http://. » and files on FTP servers by «ftp://. » etc.

    ADSI in a nutshell
    As Microsoft puts it, “ADSI is a set of COM programming interfaces that will make it easy for customers and Independent Software Vendors (ISVs) to build applications that register with, access, and manage multiple directory services with a single set of well-defined interfaces” (Ref.1) Active Directory Service Interfaces abstract the capabilities of individual directory services: which means you, as a developer, could access a file system the same way you access an email server or any other service that supports ADSI.

    ADSI objects are Component Object Model (COM) Objects. You needn’t learn a new API for ADSI programming. You can develop for ADSI using simple Automation concepts. All ADSI objects support (and must support) IDispatch, so you can choose to use Late Binding or Early Binding. (Delphi supports both, quite magnificently) Here’s a small example of how to create a user on Windows NT 4.0 using Early Binding.

    var
    Container : IADsContainer;
    NewObject : IADs;
    User : IADsUser;
    hr : HREsult;
    begin
    // COM must be initialized
    CoInitialize(nil);

    // Bind to the container.
    hr := ADsGetObject(‘WinNT://YOURDOMAIN’,IADsContainer,Container);
    if Failed(hr) then exit;
    // Create the new Active Directory Service Interfaces User object.
    NewObject := Container.Create(‘User’,’ActiveDirectoryUser’) as IADs;
    // Get the IADsUser interface from the user object.
    NewObject.QueryInterface(IID_IADsUser, User);
    // Set the password.
    User.SetPassword(‘Borland’);
    // Complete the operation to create the object.
    User.SetInfo;
    // Cleanup.
    Container._Release;
    NewObject._Release;
    User._Release;
    CoUninitialize;
    end;

    Note: The ADsGetObject function is declared in AdsHlp.pas that is included with this article. The interface definitions are imported from ActiveDS.tlb in the WinNT/System32 folder. You will need to install ADSI 2.5 from http://www.microsoft.com/ntserver/nts/downloads/other/ADSI25/default.asp.
    I will explain the architecture in more detail in the Architecture section. Active Directory Service Interfaces can be used easily in Delphi, though all the examples and support in the http://www.microsoft.com/adsi are in Visual Basic or C++ code. With this paper, you will find all the translations of the header files, some samples and some new Delphi translations.

    A Directory Service Provider is a module that gives a user access to a certain directory service. For instance, we were able to add a user to the Windows NT user manager because Microsoft has written an ADSI provider for the user manager.

    This doesn’t sound very great, you might say. What’s the difference between doing this and using native Windows NT calls to add users? First, this is COM based so if Microsoft decides to change the entire implementation of the user architecture, your applications are safe, because there will still be an ADSI provider supporting the same interfaces. (Note: this kind of thing might not be about to happen.)
    Second, consider your gains in extensibility. You can now add a user on a Netware Server using very similar code, except you’d have to use the ADSI provider for Netware. As we will see later, the code will follow a similar pattern for doing different activities: creating a web site, adding an email user etc.
    Take a look at the next section for more benefits.

    Why should you use ADSI?

    Open Any directory provider can implement an Active Directory Service Interfaces provider; users can easily move to a different provider of the same service with a minimum rewrite.
    Security ADSI supports both Authentication and Authorization programming model — You can give even role based security for your applications.
    Simple Programming Model As you will see, the COM model is very easy to understand. The model remains standard for all providers: there’s no need to understand vendor specific APIs.
    Automation Server Any Automation Controller (for example, Delphi, Visual Basic, C/C++ and others) can be used to develop directory service applications. Administrators and developers can use the tools they already know.
    Functionally Rich ISVs and sophisticated end users can develop serious applications using the same Active Directory Service Interfaces models that are used for simple scripted administrative applications.
    Extensible Directory providers, ISVs, and end users can extend Active Directory Service Interfaces with new objects and functions to add value or meet unique needs.

    The Architecture of ADSI

    This section deals with the core concepts of ADSI. There will be

    1. a description of the COM object model and
    2. an introduction to the various interfaces

    Overview
    Most directory services are hierarchical in nature and thus lend themselves to a hierarchical object model. ADSI abstracts this concept by defining Container Interfaces and leaf interfaces. A container object (that implements a Container Interface) will contain zero or more ADSI objects — which could be other containers or leaf objects. As I’ve said before, access to directory services is through ADSI providers — so each provider is identified by a unique namespace identifier. A provider implements a Namespace object which is a COM Object that is a one-stop-shop: you can access any object in the namespace through this object.

    These namespace objects are stored in an Active Directory Namespace Container object which is identified by the name «ADS:». (See Figure).

    Each Namespace object is itself a container — it contains the root nodes of the directory service objects. Every container object and leaf object support a common set of methods — so that users can interact with it uniformly. These common methods are part of the IADs interface for all nodes, and IADsContainer interface for container nodes.

    These common methods do not expose all the functionalities of a provider — simply because the domain of a «directory service provider» is too large to be able to abstract everything. To allow providers to extend functionality, ADSI supplies a schema model that I will describe later.

    COM Object Model

    There are many ADSI Interfaces that have been defined for specific purposes. Here is a list:

    IADs Object Identification
    Fundamental interface required on all ADSI objects. You use this interface to get and set properties.
    IADsContainer Object Lifetime Management and Detection
    Fundamental interface to be supported on all ADSI container objects. Manages object creation, deletion, copying and moving, binding, and
    IADsPropertyList Object Property Management
    Manages an objects properties in the property cache. You can use this to get and set properties. (Alternatively from IADs)
    IDirectoryObject Direct Object Access
    Low-level object access for clients that do not want to use Automation (Early binding) . Really useful when you want to get/set many properties in one call, instead of using multiple IADs.Get or IADs.Set calls..
    IUnknown COM Object Management
    Required on all COM objects.
    IDispatch Type Library Information and Method Invocation
    Required on all Automation objects. ADSI Objects must support this interface.

    As an analogy, consider any Delphi application. There’s a global object called Screen that contains information about all the forms created(Screen.Forms). Each form has a set of standard properties (Name, Tag for example).

    Each form could contain many components in it, each of which has the standard properties (Name, Tag) at least. So a Form is analogous to a «container» in ADSI. In congruence, Screen is also a container.

    Taking this further, a «Form» is a namespace — Any object in this namespace is derived from TForm and thus supports everything that TForm does. One more thing: ADSI requires that any object has a unique name: if we assume that all forms had unique names (which they usually will), then I could identify any object (Form ) by using its name. If I had to register this globally — I would prefix the name with «Form:». (Form:MainForm for instance). So «Form:» is handled by the Screen object which figures out where «Mainform» is. (You could have other namespaces handled by other containers)

    To translate this to ADSI, we would have to have TForm support :

    • IADs (All ADSI objects)
    • IADsContainer (All ADSI Container objects)

    All components (hosted on TForms) should support

    TScreen should support

    • IADs (All ADSI objects)
    • IADsContainer (All ADSI Container objects)
    • IADsOpenDSObject (All ADSI Namespace container objects)

    (This is only an example to demonstrate the ADSI object model. It might not be the best way to have your application support ADSI.)

    If this was implemented, you can create any form by calling Screen.OpenDSObject(‘Form:MainForm’);. With ADSI, there are libraries present so that you can open an object directly, given its path. You don’t need to create the namespace container in order to create an object. A few functions here are:

    • ADsGetObject(Path, Interfacename, Object) — returns an instance of the object who’s name is Path. To avoid round trips with QueryInterface, (See Effective COM by Don Box et. al) the second parameter is an Interface ID that determines which interface will be returned.
    • ADsOpenObject — Similar to ADsGetObject, except you can log on using a different identity to get the parameters. The security model in ADSI works with NT User security, so you can have role based security work for you.
    • ADsBuildEnumerator, ADsEnumerateNext, ADsFreeEnumerator — Helper functions for the IEnumVARIANT interface, which allows Visual Basic developers to use the for each syntax.

    Using ADSI in Delphi

    In this section I will talk about how you can use ADSI in Delphi. I’ve used a number of samples from the Windows Platform SDK as a reference. If you take a look at this, most examples you will find will use late binding : Visual Basic code or VBScript/ASP code. I’ll use a combination of Late and Early Binding — Delphi can use both — to demonstrate various features.

    Binding to an ADSI object and enumeration

    Binding string
    A directory may contain a large number of items. Each item must be uniquely identifiable. ADsPath is a property available on any ADSI object which uniquely identifies it, both on a particular provider and across providers. Each provider corresponds to a namespace: Consider a few ADSI providers that ship with ADSI.

      WinNT: — The Windows NT prov >(The initial elements of the ADsPath string are the namespace identifier (progID) of the ADSI provider, followed by «//», followed by whatever syntax is dictated by the provider namespace)

    With this information at hand, lets consider a few ADsPaths that could identify objects.

      WinNT://MyDomain/Adminstrator — >To find all the providers installed on your machine, you can enumerate the namespaces in «ADs:». Here is some Visual Basic code that does it:

    Set x = GetObject(«ADs:»)
    For Each provider In x
    provider.Name
    Next

    Since we do not have the «For Each» syntax in Delphi, I will use the helper functions provided by ADSI to enumerate containers.

    var x : IADsContainer;
    e : IEnumVariant;
    hr, i : integer;
    varArr : OleVariant;
    lNumElements : ULONG;
    item : IADs;
    begin
    hr := ADsGetObject( ‘ADs:’, IID_IADsContainer, x); // bind to the object
    hr := ADsBuildEnumerator(x,e); // start enumerating
    while SUCCEEDED(hr) do
    begin
    // get the next contained object
    hr := ADsEnumerateNext(e,1,varArr,lNumElements);
    if (lNumElements nil then
    hr := ADsFreeEnumerator(e);
    end;

    The binding code is in ADsGetObject( ‘ADs:’, IID_IADsContainer, x);
    This code is a bit complex and troublesome to do everytime. I’ve added a funtion that allows easy enumeration.

    procedure ADsEnumerateObjects(Container : IADsContainer;
    Func : TADsEnumCallback);
    var
    e : IEnumVARIANT;
    varArr : OleVariant;
    lNumElements : ULong;
    obj : IADs;
    hr : integer;
    begin
    hr := ADsBuildEnumerator(Container,e);
    while(Succeeded(Hr)) do
    begin
    hr := ADsEnumerateNext(e,1,
    varArr ,lNumElements);
    if (lNumElements=0) then
    break;
    IDispatch(varArr).QueryInterface(IADs, obj);
    if obj<>nil then
    begin
    Func(obj);
    end;
    varArr := NULL;
    end;
    // do not call ADsFreeEnumerator(e); since e will be released by Delphi
    end;

    You can use this in a Delphi form like so:

    procedure TForm1.Button2Click(Sender: TObject);
    begin
    ADsEnumerateObjects(‘ADs:’, Callback);
    end;
    procedure TForm1.Callback(Obj: IADs);
    var
    s : string;
    begin
    ShowMessage(Obj.name);
    end;

    You may also use ADsOpenObject for binding, the only difference being that you can choose to bind as a different user instead.

    hr := ADsOpenObject(‘IIS://localhost’, ‘Admin’,’Admin’,
    ADS_SECURE_AUTHENTICATION , IADs, obj );

    Connection Caching
    ADSI caches connections to servers — on all objects not yet destroyed. So, if you will bind to many objects, you can create a dummy object that binds to some object on the server, perform your set of operations using a different set of objects and finally, released the dummy object.

    Accessing properties.

    Once Binding is established, you will want to get or set properties of the object. The steps involved are:

    a) Bind to the object
    b) Set properties
    c) Call SetInfo
    d) Release the object

    (b) and (c) are required because ADSI caches the properties on the client side and updates the server only when you call SetInfo. (Saves a lot of network traffic this way).

    Here’s an example.

    // Late Binding
    var obj : Variant;
    begin
    obj := ADsHlp.GetObject(‘WinNT://AGNISOFT/Deepak’); // bind to the object
    obj.Put( ‘FullName’, ‘Deepak’); // set properties
    obj.SetInfo;
    obj := NULL; // release the object
    end;

    Note: In ‘WinNT://AGNISOFT/Deepak’, AGNISOFT is the Active Directory Domain and Deepak is the user name. FullName is a property of every user.(earlier accessible using User Manager for Domains)

    Properties could also have multiple values, like additional phone numbers. You would use the PutEx and GetEx functions to set or access these properties.

    var obj : IAds;
    begin
    ADsGetObject(‘LDAP://CN=deepak,CN=Users,DC=AGNISOFT,DC=COM’,
    IAds, Obj);
    // assume there was ‘111-1111’ and ‘222-2222’
    obj.PutEx(ADS_PROPERTY_APPEND, ‘otherHomePhone’,
    VarArrayOf([‘333-3333’]) );
    obj.SetInfo; //now there will be ‘111-1111’,
    //’222-2222′ and ‘333-3333’
    obj.PutEx(ADS_PROPERTY_DELETE, ‘otherHomePhone’,
    VarArrayOf([‘111-1111’, ‘222-2222’]));
    obj.SetInfo; //now there will be only ‘333-3333’
    obj.PutEx(ADS_PROPERTY_UPDATE, ‘otherHomePhone’,
    VarArrayOf([‘888-8888′,’999-9999’]));
    obj.SetInfo; //now there will be ‘888-8888’
    //and ‘999-9999’
    obj.PutEx(ADS_PROPERTY_CLEAR, ‘otherHomePhone’, NULL);
    obj.SetInfo;//now there will be nothing
    end;

    Searching Active Directory

    1. Using ADO
    Active Data Objects is Microsoft’s latest Database Access solution. It works with OLE DB providers, and ADSI comes with a provider named «ADsDSOObject«. In Delphi, all you need to do is to drop a TADOConnection and set its provider to «ADsDSOObject». Then, drop a TADOQuery, connect it to the TADOConnection and query ADSI — this is a method for simple searching.

    Here’s how I’ve got all the users, their user names and their last names from my machine’s Active Directory.

    The SQL syntax is :
    SELECT [ALL] select-list FROM ‘ADsPath’ [WHERE search-condition] [ORDER BY sort-list]

    The Query I have used in the form is

    SELECT AdsPath, CN, SN FROM ‘LDAP://DC=AGNISOFT,DC=COM’ WHERE object ORDER BY sn

    The ADSI provider is read-only at this time. Microsoft plans to ship a read-write provider in future. To modify data, you can:
    1. Get the ADsPath from the Query
    2. Use ADsGetObject to bind to the ADsPath
    3. Get/Set properties

    At this point, only the LDAP and the NDS providers support searching using ADO. You cannot use ADO to search for user in a Windows NT (Or 2000) domain.
    2. Using COM Interfaces — IDirectorySearch

    If you don’t want to use ADO, you can use the IDirectorySearch Interface. The steps involved are:
    1. Bind to the object
    2. Call QueryInterface on the object for IDirectorySearch
    3. Call IDirectorySearch.ExecuteSearch, passing the search query and get a search handle
    4. Call IDirectorySearch.GetNextRow and for each row, call IDirectorySearch.GetColumn(columnName) to get the columns.

    // bind to the object
    AdsGetObject(edtObjectPath.Text, IDirectorySearch, search);
    try
    // set parameters
    opt[0].dwSearchPref := ADS_SEARCHPREF_SEARCH_SCOPE;
    opt[0].vValue.dwType := ADSTYPE_INTEGER;
    opt[0].vValue.Integer := ADS_SCOPE_SUBTREE;
    search.SetSearchPreference(@opt[0],1);
    // search
    p[0] := StringToOleStr(‘Name’);
    search.ExecuteSearch(‘(objectCategory=Group)’,@p[0], 1, ptrResult);
    // get records
    hr := search.GetNextRow(ptrResult);
    while (hr <> S_ADS_NOMORE_ROWS) do
    begin
    hr := search.GetColumn(ptrResult, p[0],col);
    if Succeeded(hr) then
    begin
    ShowMessage(col.pAdsvalues^.CaseIgnoreString);
    search.FreeColumn(col);
    end;
    Hr := search.GetNextRow(ptrResult);
    end;
    search.CloseSearchHandle(ptrResult);
    finally // free memory
    search._Release;
    end;

    Security

    ADSI supports Authentication using a login name and a password. If you use ADsGetObject then the user currently logged on is used to authenticate the login. You can specify a user name by using ADsOpenObject.

    Example:
    hr := ADsOpenObject(‘IIS://localhost’, ‘testuser’,’pwd’,
    ADS_SECURE_AUTHENTICATION , IADs, obj );

    ADS_SECURE_AUTHENTICATION specifies that Kerberos or NTLM is used to authenticate the password. You can even specify password encryption (if your server supports it).

    Role based security to properties — You might need to secure ADSI itself — control who can read/write certain properties etc. The properties of ADSI are controlled by Access Control Entries (ACEs) in Windows 2000. You can create an ACE and add it to the Discretionary Access Control List (DACL) of the SecurityDescriptor of an object. ( Use obj.Get(‘ntSecurityDescriptor’) to get the security descriptor) The ACE can allow or deny access to one or all properties of an object. The security is inherited — so if you change the access control list of a container, all its descendants will inherit it.

    Supporting ADSI

    In the Windows 2000 application specification, it is recommended that you use ADSI in your applications in specific instances.

    1. If your application will use a known directory service, you must use ADSI to get or set properties in the Active Directory service. For instance, if you need to add or modify a user, you must use ADSI to do so.
    2. In a client-server or multi-tier application, you are suggested to publish server attributes in the Active Directory. Which means that the client applications should be able to use ADSI to get all the information about the server application.

    To do this, you need to be able to extend ADSI. I’ll talk about two ways you could extend ADSI. But first, lets see how the ADSI Schema works.

    ADSI Schema

    The predefined ADSI objects have very few properties: these may not be enough for a particular provider. So, ADSI allows your provider to extend the basic interface by adding properties to objects within your namespace. The schema objects are special ADSI objects : They allow you to :

    — Browse the definition of objects
    — Extend the definition of objects

    The schema object contains definitions of :

    1. What kind of objects will be present (eg. in WinNT:, you have Users, Groups, Services etc),
    2. What properties these objects will have (For Users in WinNT:, FullName, Description etc. are properties) and which properties are mandatory and which are optional.
    3. The syntax of these properties (FullName is a String, UserFlags is an integer etc.)

    (1) above is represented by a Class Object.
    (2) by a Property Object
    (3) by a Syntax object

    These three are placed in the Active Directory as follows:

    To browse the schema of an object, you must:
    1. Get the ADsPath of the schema — The IADs.Get_Schema call does the job
    2. create the schema object and browse it.
    Here’s an example that gets the list of Mandatory and optional properties of all Users in the LDAP namespace.

    var obj : IAds;
    s : WideString;
    cls : IADsClass;
    cont : IADsContainer;
    i : integer;
    begin
    AdsGetObject(‘LDAP://CN=Users,DC=AGNISOFT,DC=COM’, IADs, obj );
    s := obj.Get_Schema;
    AdsGetObject(s, IADsClass, cls );
    if VarIsArray(cls.MandatoryProperties) then
    begin
    for i := VarArrayLowBound(cls.MandatoryProperties,1) to
    VarArrayHighBound(cls.MandatoryProperties,1) do
    begin
    s := cls.MandatoryProperties[i];
    ShowMessage(‘MANDATORY:’ + s);
    end;
    end;

    if VarIsArray(cls.OptionalProperties) then
    begin
    for i := VarArrayLowBound(cls.OptionalProperties,1) to
    VarArrayHighBound(cls.OptionalProperties,1) do
    begin
    s := cls.OptionalProperties[i];
    ShowMessage(‘Optional:’ + s);
    end;

    end;

    Here’s a small application screenshot that does this:

    ADSI Extensions

    ISVs or corporate developers can extend the object semantics by adding interfaces to the existing ADSI interfaces. ADSI combines the COM Aggregation model and directory technology to bring a powerful extension model. You can thus support more functions than provided by any of the standard ADSI interfaces.

    Anyone that needs to extend ADSI can do so by writing an extension — which is nothing but a COM object. A backup vendor, for instance, could write an extension that supports «Backup» and «Restore» functions that extend the IADsComputer interface — This would be useful for administrator to write scripts for automatically backing up computers to a tape drive.

    Writing Providers

    To provide access to a totally new namespace, you must implement an ADSI provider. An ADSI provider could just be a single COM DLL containing many COM classes that you implement. Any provider needs to support:

    1. A top level namespace object that supports IADsOpenDSObject and IParseDisplayName. (And of course, IADs) YOu will need to parse any AdsPath given and detect syntax errors, if any. 2. A few other interfaces-IADsPropertyList, IADsPropertyEntry, IADsPropertyValue, IDirectoryObject. (I won’t go into detail on these interfaces)
    3. IDispatch — this is very important because you must support late binding.
    4. IADsContainer on all object containers.
    5. IEnumVariant on all enumeratable objects (containers, collections).- You need to support those Visual Basic and VBScript users using for each.
    6. A schema class container object with appropriate class, syntax and property objects for your namespace.

    This seems like quite a big task, and though there is a sample in the Windows 2000 platform SDK, it isn’t quite easy. I have written a sample in order to make it easier for you to begin — it’s available along with this article.

    Conclusion.
    Windows 2000 supports Active Directory natively-there are four providers (WinNT:, LDAP:, IIS:, NDS:) already present in the Windows 2000 server install. At the time of writing this paper, the other applications supporting ADSI are Microsoft Exchange Server 5.5 and Microsoft Site Server 3.0. Many third-party products are coming out with ADSI support.
    There will be a lot of focus on ADSI in the future — you will see a number of components that will give you easier access to ADSI objects. You can begin to perform administrative tasks using ADSI, and identify areas of your applications where it will be better to use ADSI rather than a native Directory provider.

    Active Directory is not something to be ignored because it forms a part of the most recent operating system that you will support — Windows 2000.

    References
    1. ADSI White Papers — part of the Windows Platform SDK
    2. Windows 2000 Developers Readiness Kit.
    3. Newsgroups : (at msnews.microsoft.com)
    — microsoft.public.adsi.general
    — microsoft.public.platformsdk.adsi

    © 1998-2012, Agni Software (P) Ltd. All Rights reserved.

    Переход на механизмы авторизации и аутентификации ADFS как часть маркетинговой стратегии

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

    А самое главное, она пригодится тем, кому важны потребительские качества IT-продукта, его значение и удобство для конечного пользователя.

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

    Это система лояльности для кассиров, которые продают услуги нашего заказчика. Выполнена на MS SharePoint. Через портал кассиры копят бонусы и получают за них подарки (сувенирку, турпутевки, подарочные карты и т.п.) Компания таким образом может гибко управлять продажами нужных «позиций», анализировать работу кассиров и агентств и много еще чего полезного.

    Мы разрабатывали программу лояльности с самого начала. Первый релиз состоялся в феврале 2013 года. Развитие системы продолжается. Например, только что мы провели полный редизайн портала. Но этому предшествовала миграция на ADFS, как важнейший этап модернизации. Об этом — дальше речь.

    Вкратце схему работы ADFS можно описать так:

    Клиент заходит на портал, веб-сервер портала перенаправляет клиента на сервис ADFS для авторизации. Здесь клиент проходит авторизацию и получает от сервиса авторизации «CLAIM» (маркер), затем с помощью данного маркера авторизуется на портале.

    Миграция на ADFS

    Программа лояльности является частью сложного решения на базе SharePoint, которое состоит из разных подсистем, живущих на разных сайтах. Нужно было обеспечить Single Sign On во все эти продукты, упростить и брендировать вход, сделать его более привычным для пользователей.

    В данном случае требовалось не создание решения с нуля, а «миграция авторизации» с «classic ntlm» на ADFS. И мы пошли своим классическим путем отработанной многоэтапной подготовки к переносу:

    1. Развернули у себя на тестовой площадке прототип решения и начали отрабатывать ошибки.
    2. Убедившись, что все заработало, составили документацию по развертыванию решения и отправили ее заказчику, чтобы он развернул решение у себя.
    3. Протестировали у заказчика на тестовой конфигурации.
    4. Успешно провели боевую миграцию.
    Анализируем собственное решение

    Итак, для начала анализируем, что нам нужно для перехода:

    1. У нас есть список пользователей сайта (несколько тысяч), которых надо заменить на claim записи.
    2. У нас есть списки и библиотеки документов с кастомными разрешениями. И нужно, чтобы после миграции у новых пользователей права остались прежними.
    3. У нас есть куча кастомного кода (веб-части, страницы, хендлеры и т.д.), в котором проверяется уровень доступа пользователя через AD. Все это надо прорефакторить и переписать с учетом того, что пользователи могут быть клеймовые.
    4. Так как мы переключаем на ADFS не весь портал, а только отдельный узел, то придется узел выделить в отдельное веб-приложение. Но часть данных используется с корневого узла, поэтому необходимо вынести слой работы с данными в WCF-сервис, с помощью которого будем эти данные в нашем новом приложении получать.

    Начинаем процесс:

      Начали с 4 пункта – выделения получения данных с корневого узла в отдельный сервис и последующего отделения нашего узла в отдельное приложение.

    По первой части особых проблем не возникло – обыкновенный рефакторинг кода и настройка WCF сервиса. Пара недель – и все работает.
    С отделением узла в отдельное приложение возникли некоторые сложности. В основном они были связаны с тем, что надо было при импорте/экспорте убедиться, что все данные сохранились, юзеры перетащились, права остались. Но так как данных на узле было достаточно много, то процедура импорта/экспорта занимала часа 3, и при неудачном исходе приходилось все это дело запускать заново и терпеть снова.

    Самой долгой и непонятной проблемой до некоторых пор была проблема с импортом юзеров. Они импортировались вроде бы нормально, но вот права на списки и библиотеки и поля с типом User никак не хотели восстанавливаться.

    После долгих и мучительных поисков причин выяснилось: проблема в том, что портал был ранее мигрирован с SharePoint 2007 на SharePoint 2010, и в схеме списков описание поля типа User было неполным. Пришлось для начала прогонять утилиту (написанную своими руками), потом опять делать экспорт/импорт. После этого импорт состоялся успешно.
    Теперь можно переключать новое приложение на ADFS. Идем по стандартной процедуре:

    a. Устанавливаем доверенный ADFS-сервер и сертификат через powershell скрипт

    b. Меняем настройки аутентификации приложения

    c. Мигрируем юзеров для того чтобы все разрешения стали через Claims (опять через powershell скрипт)

    d. После этого обновляем все существующие учетные записи и приводим их к Claim записи вида i:0e.t|ADFS Federated Server|user@company
    После этого все заработало в целом. Потом еще долго тренировались локально и на тестовых серверах.

    Боевое переключение и проблемы

    Боевое переключение делали в субботу, так как время только на экспорт/импорт уходило около 5 часов. В итоге со всеми мелкими проблемами начали в 9 утра, закончили в 12 ночи :)

    В целом все заработало сразу нормально, так как до этого все оттренировали и оттестили на тестовом окружении. Но вылез один баг, который на тестовом у нас не повторялся никогда (и до сих пор не повторяется) — проблема логаута в Internet Explorer.

    Суть в следующем:

    Для выхода используется редирект на страницу ADFS-сервера вида adfs.ru/adfs/ls/?wa=wsignout1.0&Source=yoursiteurl

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

    Так вот, чтобы выход в SharePoint прошел корректно, необходимо при вызове этой страницы выхода передать в запросе авторизационный cookies FedAuth/

    Как оказалось, в IE это происходит не всегда, и получался эффект, когда мы жмем выход, но выйти не можем.

    В итоге пришлось немного подправить url выхода, чтобы после отработки страницы логаута ADFS вызывалась напрямую страница логаута SharePoint, а после нее обратно страница авторизации ADFS:

    Заключение

    Почему миграция программы лояльности на ADFS оказалась важна для заказчика?

    1. ADFS дает возможность авторизоваться на портале с помощью дружелюбного логина-пароля вместо устрашающей стандартной Windows Authentication формы. Также, если пользователь забыл пароль, система любезно его подскажет, не нужно будет разыскивать админа и доказывать ему, что ты не верблюд.
    2. Такой вход можно брендировать корпоративными цветами и символикой и подогнать под единые корпоративные визуальные стандарты.
    3. ADFS дает возможность настроить single sign on авторизацию, и юзеры смогут не плодить учетные записи, а заходить в систему с помощью своих аккаунтов в соцсетях. Что не может не сказаться на их душевном равновесии и позитивном настрое на работу :)
    4. ADFS отлично подходит для применения в таких сложных систем, как нашего заказчика, т.к. предоставляет функционал единого входа к разным веб-приложениям в течение одного сеанса работы.

    Архитектура Membership API

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

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

    Для преодоления этой проблемы в ASP.NET 2.0 было добавлено средство под названием , которое в ASP.NET 4, по сути, осталось без изменений. Интерфейс Membership API — это платформа, построенная на основе существующей инфраструктуры аутентификации с помощью форм. При использовании Membership API даже не понадобится реализовывать страницы входа или хранилища удостоверений.

    Платформа Membership API предоставляет полный набор готовых функций управления пользователями:

    Возможность создавать и удалять пользователей — как программно, так и с помощью веб-утилиты конфигурирования ASP.NET.

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

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

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

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

    Уровень абстракции, который обеспечивает независимость приложений от конкретного лежащего в основе хранилища данных через классы поставщиков членства. Любая функциональность, перечисленная выше, работает совершенно независимо от конкретного используемого хранилища данных, и одни хранилища данных можно заменять на другие — совершенно без необходимости в какой-либо модификации приложений. По умолчанию Membership API полагается на базу данных SQL Server Express для хранения информации о пользователях и ролях.

    На рисунке ниже показана фундаментальная архитектура Membership API, которая состоит из поставщиков, собственно API-интерфейса и элементов управления для создания соответствующих пользовательских интерфейсов:

    Платформа Membership API спроектирована для полностью независимой работы от используемого им хранилища данных. Вы, как разработчик приложения, в основном имеете дело с элементами управления, предоставленными ASP.NET, а также классом Membership. Класс Membership предлагает набор методов для программного доступа к пользователям и ролям, находящимся в хранилище. Методы работают с поставщиком членства. Этот поставщик реализует доступ к лежащему в основе хранилищу данных. Все классы, относящиеся к Membership API, размещены в пространстве имен System.Web.Security. Их список с краткими описаниями приведен в таблице ниже:

    Классы Membership API

    Класс Membership — центральная точка взаимодействия с Membership API. Он предоставляет ряд методов для управления пользователями, их проверки и переустановки паролей

    Исключение, генерируемое в случае возникновения ошибки при попытке создания пользователя классом Membership

    Представляет отдельного пользователя, записанного в хранилище данных Membership API. Этот объект содержит всю информацию о пользователе и возвращается несколькими методами класса Membership, например, GetUser()

    Коллекция пользователей Membership. Например, метод GetUsers() класса Membership возвращает экземпляр этой коллекции

    Базовый класс, от которого наследуются собственные классы поставщиков членства, которые аутентифицируют пользователей по специальному хранилищу удостоверений

    Коллекций доступных поставщиков членства на машине для данного веб-приложения

    Реализаций класса MembershipProvider, работающая с базами данных SQL Server

    Реализация класса MembershipProvider, работающая со службой Active Directory

    Класс, который наследует всю функциональность MembershipUser и добавляет некоторые специфичные для Active Directory свойства

    ASP.NET включает готовых поставщиков членства для SQL Server и Active Directory (что позволяет создавать собственные страницы входа для пользователей, хранящихся в Active Directory). Но основная идея поставщиков состоит в том, что они предоставляют возможность полного расширения инфраструктуры. Таким образом, можно реализовать собственный поставщик членства, который будет представлять собой класс, унаследованный от System.Web.Security.MembershipProvider. Поставщик членства конфигурируется, прежде всего, в файле web.config, в новом разделе .

    Хотя Membership API и поддерживает службу Active Directory в качестве одного из поставщиков, все же существует большая разница между использованием Windows-аутентификации и Membership API для аутентификации пользователей веб-приложений.

    В случае настройки приложения на применение интерфейса Membership API, который в действительности основан на аутентификации с помощью форм, удостоверения пересылаются по сети в виде простого текста (если только не используется SSL) и, как было показано ранее, для аутентификации применяются так называемые билеты аутентификации. С другой стороны, при настройке Windows-аутентификации пользователь аутентифицируется либо через NTLM, либо через Kerberos (в случае доменов Windows Server). Оба метода намного более безопасны, поскольку удостоверения никогда не пересылаются через сеть.

    В приведенной таблице присутствует выделенный класс по имени ActiveDirectoryMembershipUser, который применяется в сочетании с ActiveDirectoryMembershipProvider. Однако класса по имени SqlMembershipProviderUser вы не найдете. Это значит, что класс SqlMembershipProviderUser для представления пользователей использует базовый класс MembershipUser. Причина в том, что версия поставщика Active Directory расширяет класс MembershipUser множеством специфичных для Active Directory атрибутов, доступных пользователям Active Directory. Таких специфичных свойств у SqlMembershipProviderUser не предусмотрено, поэтому создание отдельного класса SqlMembershipProviderUser просто не понадобилось.

    Интерфейс Membership API служит только для управления и аутентификации пользователей. Он не реализует никакой функциональности авторизации и не предоставляет функциональности управления пользовательскими ролями. Для этой цели предназначен интерфейс Roles API рассматриваемый позже.

    Asp объекты adsi

    ADSI can be used to access directory data using an ASP page. This can be a convenient way to run administration tasks and queries from a webpage or provide information to employees on an intranet.

    One advantage of using ADSI with ASP is that you can create a richer user experience because you can use Visual Basic to create an ADSI application and offer it to a user through a standard webpage. For example, you could create a webpage that enables employees to enter the last name of an employee and get back a phone number for that employee, or create a form that allows employees to update personal information in a company human resources database.

    ASP code starts with ‘ ‘. You can add ADSI code as VBScript or Visual Basic.

    To create an ASP page, you can use a webpage editor, Notepad or other text editor, or the Microsoft Visual Studio .NET development system.

    Before you run your ASP page, set up your application or IIS server according to the instructions found in Authentication Issues for ADSI with ASP.

    A Simple ASP Sample: Enumerating Objects in a Container

    Using a webpage editor, create a new html page which accepts the distinguished name of a container object. Enter the following code example.

    This page can now accept a container name that is passed to it and use ADSI to enumerate objects in the container.

    Илон Маск рекомендует:  Экспорт товаров в Яндекс.Маркет в формате YML при помощи PHP-класса
    Понравилась статья? Поделиться с друзьями:
    Кодинг, CSS и SQL
    Компонент Описание
    Membership
    MembershipCreateUserException
    MembershipUser
    MembershipUserCollection
    MembershipProvider
    MembershipProviderCollection
    SqlMembershipProvider
    ActiveDirectoryMembershipProvider
    ActiveDirectoryMembershipUser