mirror of https://github.com/OpenIdentityPlatform/OpenDJ.git

Mark Craig
20.22.2012 65ea0c1d31cf2b495ee665c00cf95ac4871e1aa5
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
<?xml version="1.0" encoding="UTF-8"?>
<!--
  ! CCPL HEADER START
  !
  ! This work is licensed under the Creative Commons
  ! Attribution-NonCommercial-NoDerivs 3.0 Unported License.
  ! To view a copy of this license, visit
  ! http://creativecommons.org/licenses/by-nc-nd/3.0/
  ! or send a letter to Creative Commons, 444 Castro Street,
  ! Suite 900, Mountain View, California, 94041, USA.
  !
  ! You can also obtain a copy of the license at
  ! trunk/opendj3/legal-notices/CC-BY-NC-ND.txt.
  ! See the License for the specific language governing permissions
  ! and limitations under the License.
  !
  ! If applicable, add the following below this CCPL HEADER, with the fields
  ! enclosed by brackets "[]" replaced with your own identifying information:
  !      Portions Copyright [yyyy] [name of copyright owner]
  !
  ! CCPL HEADER END
  !
  !      Copyright 2011 ForgeRock AS
  !    
-->
<chapter xml:id='chap-reading'
 xmlns='http://docbook.org/ns/docbook' version='5.0' xml:lang='en'
 xmlns:xsi='http://www.w3.org/2001/XMLSchema-instance'
 xsi:schemaLocation='http://docbook.org/ns/docbook http://docbook.org/xml/5.0/xsd/docbook.xsd'
 xmlns:xlink='http://www.w3.org/1999/xlink'
 xmlns:xinclude='http://www.w3.org/2001/XInclude'>
 <title>Searching &amp; Comparing Directory Data</title>
 
 <para>Traditionally directories excel at serving read requests. This chapter
 covers the read (search and compare) capabilities that OpenDJ LDAP Java SDK
 provides. The data used in examples here is <link xlink:show="new"
 xlink:href="http://opendj.forgerock.org/Example.ldif">available
 online</link>.</para>
 
 <section xml:id="about-searching">
  <title>About Searching</title>
  <itemizedlist>
   <para>An LDAP search looks up entries based on the following
   parameters.</para>
   <listitem>
    <para>A <firstterm>filter</firstterm> that indicates which attribute values
    to match</para>
   </listitem>
   <listitem>
    <para>A <firstterm>base DN</firstterm> that specifies where in the
    directory information tree to look for matches</para>
   </listitem>
   <listitem>
    <para>A <firstterm>scope</firstterm> that defines how far to go under
    the base DN</para>
   </listitem>
   <listitem>
    <para>A list of attributes to fetch for an entry when a match is
    found</para>
   </listitem>
  </itemizedlist>
  
  <para>For example, imagine you must write an application where users login
  using their email address and a password. After the user logs in, your
  application displays the user's full name so it is obvious who is logged in.
  Your application is supposed to go to the user directory both for
  authentication, and also to read user profile information. You are told the
  user directory stores user profile entries under base DN
  <literal>ou=People,dc=example,dc=com</literal>, that email addresses are
  stored on the standard <literal>mail</literal> attribute, and full names are
  store on the standard <literal>cn</literal> attribute.</para>
  
  <para>You figure out how to authenticate from the chapter on authentication,
  in which you learn you need a bind DN and a password to do simple
  authentication. But how do you find the bind DN given the email? How do you
  get the full name?</para>
  
  <para>The answer to both questions is that you do an LDAP search for the
  user's entry, which has the DN that you use to bind, and you have the server
  fetch the <literal>cn</literal> attribute in the results. Your search uses
  the following parameters.</para>
  <itemizedlist>
   <listitem>
    <para>The filter is
    <literal>(mail=<replaceable>emailAddress</replaceable>)</literal>, where
    <replaceable>emailAddress</replaceable> is the email address the user
    provided.</para>
   </listitem>
   <listitem>
    <para>The base DN is the one given to you,
    <literal>ou=People,dc=example,dc=com</literal>.</para>
   </listitem>
   <listitem>
    <para>For the scope, you figure the user entry is somewhere under the base
    DN, so you opt to search the whole subtree.</para>
   </listitem>
   <listitem>
    <para>The attribute to fetch is <literal>cn</literal>.</para>
   </listitem>
  </itemizedlist>
  
  <para>The following code excerpt demonstrates how this might be done in a
  minimal command-line program.</para>
 
  <programlisting language="java">// Prompt for mail and password.
Console c = System.console();
if (c == null) {
    System.err.println("No console.");
    System.exit(1);
}
 
String mail = c.readLine("Email address: ");
char[] password = c.readPassword("Password: ");
 
// Search using mail address, and then bind with the DN and password.
final LDAPConnectionFactory factory = new LDAPConnectionFactory(host,
        port);
Connection connection = null;
try {
    connection = factory.getConnection();
    SearchResultEntry entry = connection.searchSingleEntry(baseDN,
            SearchScope.WHOLE_SUBTREE, "(mail=" + mail + ")", "cn");
    DN bindDN = entry.getName();
    BindResult result = connection.bind(bindDN.toString(), password);
 
    if (result.isSuccess()) {
        String cn = entry.getAttribute("cn").firstValueAsString();
        System.out.println("Hello, " + cn + "!");
    } else {
        System.err.println("Failed to bind.");
    }
} catch (final ErrorResultException e) {
    System.err.println("Failed to bind.");
    System.exit(e.getResult().getResultCode().intValue());
    return;
} catch (final InterruptedException e) {
    System.err.println(e.getMessage());
    System.exit(ResultCode.CLIENT_SIDE_USER_CANCELLED.intValue());
    return;
} finally {
    if (connection != null) {
        connection.close();
    }
}</programlisting>
 </section>
 
 <section xml:id="about-filters">
  <title>Working With Search Filters</title>
  <para>TODO</para>
 </section>
 
 <section xml:id="send-search-request">
  <title>Sending a Search Request</title>
  <para>TODO</para>
 </section>
 
 <section xml:id="get-search-results">
  <title>Getting Search Results</title>
  <para>TODO</para>
 </section>
 
 <section xml:id="abandon-search">
  <title>Abandoning an Incomplete Search</title>
  <para>TODO</para>
 </section>
 
 <section xml:id="handle-ldap-urls">
  <title>Working With LDAP URLs</title>
  <para>TODO</para>
 </section>
 
 <section xml:id="sort-search-results">
  <title>Sorting Search Results</title>
  <para>TODO</para>
 </section>
 
 <section xml:id="about-comparisons">
  <title>About Comparing</title>
  <para>TODO</para>
 </section>
</chapter>