Perl для системного администрирования

Операторы сравнения LDAP



Таблица 6.2. Операторы сравнения LDAP



Оператор Значение
= Точное совпадение значений. Может означать и частичное совпадение, если в определении <attnbute value> используется * (например cn=Tiin 0*).
=* Соответствует всем элементам, у которых есть значения для атри-
бута <attnbute name>, независимо от того, каковы эти значения.
Если вместо <attnbute value> указать *, будет проверяться нали-
чие именно этого атрибута в элементе (например, сп=* выберет эле-
менты, у которых есть атрибуты сп).
-= Приблизительное совпадение значений.
>= Больше либо равно значению.
<= Меньше либо равно значению.

Это очень похоже на Perl, но не заблуждайтесь. Две конструкции, которые могут смутить знатоков Perl, это ~= и =*. Первая из них не имеет ничего общего с регулярными выражениями; она ищет приблизительное соответствие с указанным значением. В этом случае определение
«приблизительное» зависит от сервера. Большинство серверов применяют алгоритм, первоначально используемый в soundex для определения совпадающих значений при поиске слов, которые «произносятся, как» заданное значение (в английском языке), но записываются иначе.

Другая конструкция, которая может конфликтовать с вашими знаниями Perl, - это оператор =. Помимо проверки точного совпадения значений (как строковых, так и численных), оператор = можно использовать вместе с символом * в виде префикса или суффикса в качестве символов подстановки, подобно тому как это происходит в командных интерпретаторах. Например, сл=а* получит все элементы, имена которых (common name) начинаются с буквы «а». Строка сп=*а* выполнит именно то, чего вы ждете, и найдет все элементы, в атрибуте ел которых есть буква «а».

Можно объединить в одну строку два или более простых фильтра Ottribute пате>, <companson operator>, ottribute value> при помощи логических операторов, создав таким образом более сложный фильтр.
Он имеет следующий вид:

(<boolean operator> (<simple1>)

(<simple2>) (<simple3>) ... )

Те, кто знаком с LISP, без труда разберутся с подобным синтаксисом; всем остальным придется просто запомнить, что оператор, объединяющий простые формы поиска, записывается первым. Чтобы найти элементы, удовлетворяющие обоим критериям поиска А и В, нужно использовать запись (&(А)(В)). Для элементов, удовлетворяющих критериям А или В или С, следует применить (|(А)(В)(С)). Восклицательный знак отрицает указанный критерий: так, А и не В записывается следующим образом: (&(А)(!В)). Составные фильтры можно объединять друг с другом, чтобы создавать фильтры поиска произвольной сложности. Вот пример составного фильтра для поиска всех Финкель-
штейнов, работающих в Бостоне:

(&(sn=Finkelstein)(l=Boston))

Следующий фильтр ищет человека, чья фамилия либо Финкельштейн, либо Хайндс:

(|(sn=Finkelstein)(sn=Hinds))

Для поиска всех Финкелыптейнов, работающих не в Бостоне:

(&(sn=FinKelstein)((l=Boston)))

Для поиска всех Финкелыптейнов или Хайндсов, работающих не в Бостоне:

(&(|(sn=Finkelstein)(sn=Hinds))(!l=Boston))

Тот, кто захочет поэкспериментировать с алгоритмом soundex, может воспользоваться модулем Марка Милке (Mark Mielke) Text:: Soundex. LDAP:

Вот два примера программ, принимающих имя LDAP-сервера и фильтр и возвращающих результаты запроса:

use Mozilla::LDAP::Conn;

Sserver = $ARGV[0];

Sport = getservbyname("ldap","tcp") || "389"

Sbasean = "c=US";

Sscope = "sub";

$c = new Mozilla::LDAP::Conn($server, Sport, "",""); анонимное соединение die "Невозможно связаться с $server\n" unless $c;

Sentry = $c->search($basedn, Sscope, $ARGV[1]);

die "Ошибка поиска: ". Sc->getErrorString(),"\n" if Sc->getErrorCode()

обрабатываем полученные от search() значения while (Sentry) {

$entry->printLDIF();

Sentry = $c->nextEntry(); } $c->close();

use Net::LDAP;

use Net::LDAP::LDIF;

Sserver = $ARGV[0];

Sport = getservbyname("ldap","tcp") | "389";

Sbasedn = "c=US";

Sscope = "sub";

$c = new Net::LDAP($server, port=>$port) or

die "Невозможно соединиться с Sserver: $@\n"; $c->bind() or die "Unable to bind: $@\n"; анонимное соединение

Ssearchobj = $c->search(base => Sbasedn, scope => Sscope,

filter => $ARGV[1]);

die " Неуспешный поиск, номер ошибки и",Ssearchobj->code() if Ssearcnobj- >code();

ft обрабатываем полученные от search() значения if (Ssearchobj){

Sldif = new Net::LDAP::LDIF("-");

$ldif->write($searchobj->entries());

$ldif->done();

А вот отрывок из получаемых данных:

$ Idapsrch ldap.bigfoot.com '(sn=Pooh)'

dn: cn="bear pooh", mail=poohbear219(s>hotmail. com. c=US,o=hotmail. com

mail: poohbear219iahotmail.com

en: bear pooh

o: hotmail.com

givenname: bear

surname: pooh

Перед тем как улучшить этот пример, посмотрим на код, обрабатывающий результаты, полученные от search(). Это одно из тех мест, где модули отличаются моделью программирования. Оба примера возвращают одну и ту же информацию в формате LDIF (LDAP Data Interchange Format, формат обмена данными LDAP), о котором речь пойдет позже, но данные они получают совершенно разными способами.

Модель Mozilla: : LDAP остается справедливой для подпрограмм анализа поиска, описанных в спецификации С API в RFC1823. Если поиск был успешным, возвращается первый найденный элемент. Для просмотра результатов необходимо последовательно запросить следующие эле-
менты. Вывод содержимого каждого получаемого элемента выполняет метод printLDIF().

Модель программирования Net: : LDAP имеет больше сходства с определением протокола из RFC2251. Результаты поиска LDAP возвращаются в объекты сообщений. Для получения списка элементов из этих пакетов в предыдущем примере использовался метод entries(). Вывод
всех элементов вместе выполняет метод из смежного модуля Net:: LDAP: :LDIF. Для последовательного вывода всех элементов, как было с printLDIF() в первом примере, можно использовать похожий метод write(), но показанный выше вызов более эффективен.

Немного поработаем с предыдущим примером. Как уже отмечалось в данной главе, поиск можно выполнять быстрее, ограничив количество возвращаемых в результате атрибутов. С модулем Mozilla: : LDAP это настолько же просто, насколько просто добавить дополнительные параметры в вызов метода search():

use Mozilla::LDAP::Conn;

Sentry = $c->search($basedn,$scope,$ARGV[1],0,@attr):

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

Следующий дополнительный параметр - это список имен возвращаемых атрибутов. Знатоки Perl заметят, что список внутри списка интерполируется, так что последняя строка эквивалентна строке (ее можно так и прочитать):

Sentry = $c->search($basedn,$scope,$ARGV[1],0,$attr[0],$aTtr[1].$attr[2]. ..):

Если мы изменим строку первоначального примера:

Sentry = $c->searcn($basedn.Sscope,$ARGV[1]);

на:

@attr = qw(mail);

Sentry = $c->search($basedn,Sscope,$ARGV[l],0,@attr);

то получим следующий результат, в котором для элемента будут показаны только атрибуты DN и mail:

dn: cn="bear pooh",mail=poohbear219@notmail.com,c=US,o=hotmail.com mail: poohbear219@hotmail.com

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

use Net::LDAP;

# можно было бы добавить "typesonly => 1" для получения только

# типов атрибутов, как и в предыдущем случае для первого

# необязательного параметра

Ssearchobj = $c->search(base => Sbasedn, filter => $ARGV[1], attrs => \@attr);

Обратите внимание, что Net: : LDAP принимает ссылку на массив, а не сами значения массива, как в случае с Mozilla: : LDAP.



Содержание раздела