|
Querying an LDAP directory
The cfldap tag lets you search an LDAP
directory. The tag returns a ColdFusion query object with the results,
which you can use as you would any query result. When you query
an LDAP directory, you specify the directory entry where the search
starts and the attributes whose values to return. You can specify
the search scope and attribute content filtering rules and use other
attributes to further control the search.
ScopeThe
search scope sets the limits of a search. The default scope
is the level below the distinguished name specified in the start attribute.
This scope does not include the entry identified by the start attribute.
For example, if the start attribute is “ou=support,
o=adobe” the level below support is searched. You can restrict a
query to the level of the start entry, or extend
it to the entire subtree below the start entry.
Search filterThe
search filter syntax has the form attribute operator value. The
default filter, objectclass=*, returns all entries in the scope.
The following table lists the filter operators:
Operator
|
Example
|
Matches
|
=*
|
(mail=*)
|
All entries that contain a mail attribute.
|
=
|
(o=adobe)
|
Entries in which the organization name is
adobe.
|
~=
|
(sn~=Hansen)
|
Entries with a surname that approximates
Hansen. The matching rules for approximate matches vary among directory
vendors, but anything that “sounds like” the search string should
be matched. In this example, the directory server might return entries
with the surnames Hansen and Hanson.
|
>=
|
(st>=ma)
|
The name “ma” and names appearing after
“ma” in an alphabetical state attribute list.
|
<=
|
(st<=ma)
|
The name “ma” and names appearing before
“ma” in an alphabetical state attribute list.
|
*
|
(o=macro*)
|
Organization names that start with “macro”.
|
|
(o=*media)
|
Organization names that end with “media”.
|
|
(o=mac*ia)
|
Organization names that start with “mac”
and end with “ia”. You can use more than one * operator in a string;
for example, m*ro*dia.
|
|
(o=*med*)
|
Organization names that contain the string
“med”, including the exact string match “med”.
|
&
|
(&(o=adobe)
(co=usa))
|
Entries in which the organization name is
“adobe” and the country is “usa”.
|
|
|
(|(o=adobe)
(sn=adobe)
(cn=adobe))
|
Entries in which the organization name is
“adobe” or the surname is “adobe”, or the common name is “adobe”.
|
!
|
(!(STREET=*))
|
Entries that do not contain a StreetAddress
attribute.
|
The Boolean operators & and | can
operate on more than two attributes and precede all of the attributes
on which they operate. You surround a filter with parentheses and
use parentheses to group conditions.
If the pattern that you are matching contains an asterisk, left
parenthesis, right parenthesis, backslash, or NUL character, use
the following three-character escape sequence in place of the character:
Character
|
Escape sequence
|
*
|
\2A
|
(
|
\28
|
)
|
\29
|
\
|
\5C
|
NUL
|
\00
|
For example, to match the common name St*r Industries, use the
filter:
(cn=St\2Ar Industries).
LDAP v3 supports an extensible match filter that permits server-specific matching
rules. For more information on using extensible match filters, see
your LDAP server documentation.
Searching and sorting notesTo search for multiple values of a multivalued
attribute type, use the & operator to combine expressions for
each attribute value. For example, to search for an entry in which
cn=Robert Jones and cn=Bobby Jones, specify the following filter:
filter="(&(cn=Robert Jones)(cn=Bobby Jones))"
You can use object classes as search filter attributes; for
example, you can use the following search filter:
filter="(objectclass=inetorgperson)"
To specify how query results are sorted, use the sort field
to identify the attribute(s) to sort. By default, ColdFusion returns
sorted results in case-sensitive ascending order. To specify descending
order, case-insensitive sorting, or both, use the sortControl attribute.
ColdFusion requests the LDAP server to do the sorting. Doing
so can have the following effects:
The sort order
can differ between ColdFusion MX and previous versions.
If you specify sorting and the LDAP server does not support
sorting, ColdFusion generates an error. To sort results from servers
that do not support sorting, use a query of queries on the results.
Using filter operators to construct sophisticated search
criteria can degrade performance if the LDAP server is slow to process
the synchronous search routines that cfldap supports.
Use the cfldap tag timeout and maxRows attributes
to control the apparent performance of pages that perform queries,
by limiting the number of entries and by exiting the query if the
server does not respond in a specified time.
Getting all the attributes of an entryTypically, you do not use a query that gets all the attributes
in an entry. Such a query would return attributes that only the
directory server uses. However, you can get all the attributes by
specifying attributes="*" in your query.
If you do this, ColdFusion returns the results in a structure
in which each element contains a single attribute name-value pair.
The tag does not return a query object. ColdFusion does this
because LDAP directory entries, unlike the rows in a relational
table, vary depending on their object class.
For example, the following code retrieves the contents of the
Airius directory:
<cfldap name="GetList"
server=#myServer#
action="query"
attributes="*"
scope="subtree"
start="o=airius.com"
sort="sn,cn">
This tag returns entries for all the people in the organization
and entries for all the groups. The group entries have a different
object class, and therefore different attributes from the person
entries. If ColdFusion returned both types of entries in one query
object, some rows would have only the group-specific attribute values and
the other rows would have only person-specific attribute values.
Instead, ColdFusion returns a structure in which each attribute
is an entry.
Example: querying an LDAP directoryThe following example uses the cfldap tag
to get information about the people in the Airius corporation’s
Santa Clara office. Users can enter all or part of a person’s name
and get a list of matching names with their departments, e-mail addresses,
and telephone numbers.
This example uses the sample Airius corporate directory that
is distributed with the Netscape Directory Server. If you do not
have access to this directory, modify the code to work with your
LDAP directory.
Create a file that looks like the following:
<!--- This example shows the use of CFLDAP --->
<html>
<head> <title>cfldap Query Example</title> </head>
<h3>cfldap Query Example</h3>
<body>
<p>This tool queries the Airius.com database to locate all people in the company's
Santa Clara office whose common names contain the text entered in the form.</p>
<p>Enter a full name, first name, last name, or name fragment.</p>
<form action="cfldap.cfm" method="POST">
<input type="text" name="name"><br><br>
<input type="submit" value="Search">
</form>
<!--- make the LDAP query --->
<!-- Note that some search text is required.
A search filter of cn=** would cause an error -->
<cfif (isdefined("form.name") AND (form.name IS NOT ""))>
<cfldap
server="ldap.airius.com"
action="query"
name="results"
start="ou=People, o=Airius.com"
scope="onelevel"
filter="(&(cn=*#form.Name#*)(l=Santa Clara))"
attributes="cn,sn,ou,mail,telephonenumber"
sort="ou,sn"
maxrows=100
timeout=20000
>
<!--- Display results --->
<table border=0 cellspacing=2 cellpadding=2>
<tr>
<th colspan=4><cfoutput>#results.RecordCount# matches found</cfoutput>
</th>
</tr>
<tr>
<th>Name</th>
<th>Department</th>
<th>E-Mail</th>
<th>Phone</th>
</tr>
<cfoutput query="results">
<tr>
<td>#cn#</td>
<td>#listFirst(ou)#</td>
<td><a href="mailto:#mail#">#mail#</a></td>
<td>#telephonenumber#</td>
</tr>
</cfoutput>
</table>
</cfif>
</body>
</html>
Change the server attribute from ldap.airius.com
to the name of your installation of the Airius database.
Save the page as cfldap.cfm and run it in your browser.
Reviewing the codeThe following table describes the code:
Code
|
Description
|
<form action="cfldap.cfm" method="POST">
<input type="text" name="name"><br><br>
<input type="submit" value="Search">
</form>
|
Uses a form to get the name or name fragment
to search for.
|
<cfif (isdefined("form.name") AND (form.name IS NOT ""))>
|
Ensures that the user has submitted the
form. This is necessary because the form page is also the action
page. Ensures that the user entered search text.
|
<cfldap
server="ldap.airius.com"
action="query"
name="results"
start="ou=People, o=Airius.com"
scope="onelevel"
filter="(&(cn=*#form.Name#*)(l=Santa Clara))"
attributes="cn,sn,ou,mail,telephonenumber"
sort="ou,sn"
maxrows=100
timeout=20000
>
|
Connects anonymously to LDAP server ldap.airius.com,
query the directory, and return the results to a query object named
results.
Starts the query at the directory entry that has
the distinguished name ou=People, o=Airius.com, and searches the
directory level immediately below this entry.
Requests records
for entries that contain the location (l) attribute value "Santa Clara"
and the entered text in the common name attribute.
Gets the
common name, surname, organizational unit, e-mail address, and telephone
number for each entry.
Sorts the results first by organization
name, then by surname. Sorts in the default sorting order.
Limit
the request to 100 entries. If the server does not return the data
in 20 seconds, generates an error indicating that LDAP timed out.
|
<table border=0 cellspacing=2 cellpadding=2>
<tr>
<th colspan=4><cfoutput>#results.RecordCount# matches found</cfoutput>
</th>
</tr>
<tr>
<th>Name</th>
<th>Department</th>
<th>E-Mail</th>
<th>Phone</th>
</tr>
<cfoutput query="results">
<tr>
<td>#cn#</td>
<td>#listFirst(ou)#</td>
<td><a href="mailto:#mail#">#mail#</a></td>
<td>#telephonenumber#</td>
</tr>
</cfoutput>
</table>
</cfif>
|
Starts a table to display the output
Displays
the number of records returned.
Displays
the common name, department, e-mail address, and telephone number
of each entry.
Displays only the first entry in the list of
organizational unit values. (For more information, see the description
that follows this table.)
|
This search shows the use of a logical
AND statement in a filter. It returns one attribute, the surname,
that is used only for sorting the results.
In this query,
the ou attribute value consists of two values in
a comma-delimited list. One is the department name. The other is
People. This is because the Airius database uses the ou attribute
type twice:
In the distinguished names, at the second
level of the directory tree, where it differentiates between organizational
units such as people, groups, and directory servers
As the department identifier in each person’s entry
Because
the attribute values are returned in order from the person entry
to the directory tree root, the ListFirst function extracts
the person’s department name.
|