Операторы сравнения 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.