When you look someone up in the telephone directory, you use the value of one attribute of a person's entry (last name), to recover the person's directory entry, which has other attributes (phone number, address). LDAP works the same way. In LDAP, search requests identify both the scope of the directory entries to consider (for example, all people or all organizations), and also the entries to retrieve based on some attribute value (for example, surname, mail address, phone number, or something else). The way you express the attribute value(s) to match is by using a search filter.
LDAP search filters define what entries actually match your request. For example, the following simple equality filter says, "Match all entries that have a surname attribute (sn) value equivalent to Jensen."
(sn=Jensen)
When you pass the directory server this filter as part of your search request, the directory server checks the entries in scope for your search to see whether they match.[7] If the directory server finds entries that match, it returns those entries as it finds them.
The example, (sn=Jensen)
, shows a string
representation of the search filter. The OpenDJ LDAP SDK lets you express
your filters as strings, or as Filter
objects. In both
cases, the SDK translates the strings and objects into the binary
representation sent to the server over the network.
Equality is just one of the types of comparisons available in LDAP filters. Comparison operators include the following.
Table 6.1. LDAP Filter Operators
Operator | Definition | Example |
---|---|---|
= |
Equality comparison, as in This can also be used with substring matches. For example, to match
last names starting with |
|
<= |
Less than or equal to comparison, which works alphanumerically. |
|
>= |
Greater than or equal to comparison, which works alphanumerically. |
|
=* |
Presence comparison. For example, to match all entries having a
|
|
~= |
Approximate comparison, matching attribute values similar to the value you specify. |
|
[:dn][: |
Extensible match comparison. At the end of the OID or language subtype, you further specify the matching rule as follows:
|
You also use extensible match filters with localized values.
Directory servers like OpenDJ support a variety of internationalized
locales, each of which has an OID for collation order, such as
|
! |
NOT operator, to find entries that do not match the specified filter component. Take care to limit your search when using |
|
& |
AND operator, to find entries that match all specified filter components. |
|
| |
OR operator, to find entries that match one of the specified filter components. |
|
When taking user input, take care to protect against users providing
input that has unintended consequences. OpenDJ SDK offers several Filter
methods to help you. First, you can use strongly typed construction methods
such as Filter.equality()
.
String userInput = getUserInput(); Filter filter = Filter.equality("cn", userInput); // Invoking filter.toString() with input of "*" results in a filter // string "(cn=\2A)".
You can also let the SDK escape user input by using a template with
Filter.format()
as in the following example.
String template = "(|(cn=%s)(uid=user.%s))"; String[] userInput = getUserInput(); Filter filter = Filter.format(template, userInput[0], userInput[1]);
Finally, you can explicitly escape user input with
Filter.escapeAssertionValue()
.
String baseDN = "ou=people,dc=example,dc=com"; String userInput = getUserInput(); // Filter.escapeAssertionValue() transforms user input of "*" to "\2A". SearchRequest request = Requests.newSearchRequest( baseDN, SearchScope.WHOLE_SUBTREE, "(cn=" + Filter.escapeAssertionValue(userInput) + "*)", "cn", "mail");
[7] In fact, the directory server probably checks an index first, and might not even accept search requests unless it can use indexes to match your filter rather than checking all entries in scope.