Subversion-Projekte lars-tiefland.php_share

Revision

Details | Letzte Änderung | Log anzeigen | RSS feed

Revision Autor Zeilennr. Zeile
1 lars 1
<html>
2
<head>
3
	<title>Net_LDAP2 Manual</title>
4
	<style type="text/css">
5
		pre { border: 1px solid #000000; background-color:#EBEBEB; padding:5px; }
6
	</style>
7
</head>
8
<body>
9
<h1>Net_LDAP2 Manual</h1>
10
Welcome to the Net_LDAP2 user manual! here you have a quick introduction on
11
how to use Net_LDAP2 to acces your directory server with php.
12
<p><font color="red">Note that this manual is only a brief introduction and also may be outdated.
13
The official manual is available at the <a href="http://pear.php.net/package/Net_LDAP2/docs">PEAR project website.</a>
14
The reason this manual remains here is, that it may be useful in cases you don't have internet
15
acces at the moment.</font></p>
16
 
17
<h2>First step: Connect</h2>
18
<p>
19
To do this, use the Net_LDAP2::connect function like this:
20
 
21
<p><pre>
22
require_once('Net_LDAP22/LDAP2.php');
23
 
24
$config = array (
25
            'binddn'   => 'uid=tarjei,dc=php,dc=net',
26
            'bindpw' => 'secret',
27
            'basedn'   => dc=php,dc=net
28
          );
29
 
30
$ldap = Net_LDAP2::connect($config);
31
</pre></p>
32
</p>
33
<p>
34
But what are valid values in the config array?
35
<ul>Here's a quick table: (defaults)
36
     <li><b>binddn</b>   = the DN to bind as. (none)</li>
37
     <li><b>bindpw</b>   = Password of the user specified by 'binddn' (none)</li>
38
     <li><b>host</b>     = the ldap host to connect to (localhost)</li>
39
     <li><b>base</b>     = ldap base, this is usually the Entry point of your directory (none)</li>
40
     <li><b>port</b>     = the server port (389)</li>
41
     <li><b>starttls</b> = when set, ldap_start_tls() is run after connecting. (false)</li>
42
     <li><b>version</b>  = ldap version (defaults to v 3) </li>
43
     <li><b>filter</b>   = default search filter (objectclass=*)</li>
44
     <li><b>scope</b>    = default search scope (sub)</li>
45
</ul>
46
We'll get back to these later.
47
</p>
48
 
49
 
50
 
51
<h2>Errorhandling</h2>
52
<p>
53
Now you should have the base ldapobject stored in the variable "$ldap".
54
But, what if it is an error? Net_LDAP2 returns a Net_LDAP2_error object (basicly a
55
pear_error object) when an error occurs. So wherever you need to check an error, do like this:
56
<p><pre>
57
$ldap = Net_LDAP2::connect($config); // copied from above!
58
 
59
if (Net_LDAP2::isError($ldap)) {
60
   print $ldap->getMessage(); // this will tell you what went wrong!
61
}
62
 
63
</pre></p>
64
</p>
65
<p>
66
Two things to note:
67
 
68
<br>1) The function is_a() might be faster:
69
<p><pre>
70
if (is_a($ldap,'net_ldap_error')) {
71
// do the same as above
72
}
73
</pre></p>
74
In PHP5 you must use the instanceof operator instead of is_a().
75
 
76
<br>2) Net_LDAP2_Error can also return an errornumber. These numbers are standardized. A good description of what they mean is found there:
77
http://www.directory-info.com/LDAP2/LDAPErrorCodes.html
78
</p>
79
 
80
 
81
 
82
<h2>Searching (basics)</h2>
83
<p>
84
Most of the work you do on an ldapserver is in searching,
85
for example, you search for your boss's password or his wife's phonenumber.
86
<br>Searching an ldapserver is a bit like doing SQL and a lot not like it at all.</br>
87
Think of the directory as some sort of "telephone book".
88
Basically, searches are performed by applying a "filter" to objects under a
89
specific "base" in the directory. Additionally, there is a "scope" applied to the search,
90
so you can specify the recursion level in the directory tree.
91
</p>
92
<p>
93
<h3>Base:</h3>
94
The "base" is the point under the directory where you want to search under.
95
To search for all people under php.net, you may use: "ou=People,dc=php,dc=net".
96
But if you want just to search the devs, you can use "ou=dev,ou=People,dc=php,dc=net".
97
</p>
98
<p>
99
<h3>Filter:</h3> Filters define what you are looking for. They "filter out" unwanted entries.
100
<br>Filters start with a ( and end with a ). There is a lot to be said about filters, most is better said by examples:
101
 
102
<br><br><b>(&(objectclass=posixAccount)(uid=boss)) :</b> The object has to satisfy both filters.
103
I.e. an object that is both boss and an posixAccount. If you had another object
104
with uid=boss but that wasn't an postixaccount it would be excluded.
105
<br><b>(|(uid=boss)(uid=secretary)) :</b> Either the boss or the secretary.
106
Note that both logical operators are placed before the filters not between the
107
two conditions as you might used to from sql.
108
<br><b>(&(objectclass=posixAccount)(|(uid=boss)(uid=secretary))) :</b>
109
Here they must have the posixAccount objectclass as well.
110
 
111
<b>(objectclass=*) :</b> All objects must have an objectclass, so this is the simplest way of saying everything.
112
 
113
<b>(uid=t*) :</b> With the right indexes on the server, you may search the substring of an attriute. Here; all users with the first name beginning with a "T".
114
 
115
<br>Please note, that Net_LDAP2 provides a filter class for simplier generation and combination of filters.
116
You should use that class unless you know how filters work. This will save you a lot of trouble,
117
since there are some encoding issues with ldap-filters. If you want to provide the filter yourself,
118
you should also have a look to <a href="http://www.ietf.org/rfc/rfc1558.txt">RFC #1558</a> defining LDAP-Filters.
119
</p>
120
 
121
<p>
122
<h3>Searchscope</h3>
123
The scope of an search may be three things:
124
<ul>
125
	<li><b>'base'</b> = Just the entry in question.</li>
126
	<li><b>'sub'</b> = All subentries.</li>
127
	<li><b>'one'</b> = All entries just below the searchbase.</li>
128
</ul>
129
 
130
Searching with scope 'base' may be handy for getting just one entry. But then again, that's what the getEntry function does.
131
</p>
132
 
133
<p>
134
<h3>Searching some entries</h3>
135
We know now, how to search, so we will test out our new knowledge.
136
We want to search all person entries whose second name starts with "Ha", but only developers.
137
Later we want to know the name and the telephone number of the persons.
138
<pre>
139
$filter = '(&(objectclass=person)(sn=Ha*))';
140
$searchbase = 'ou=dev,ou=People,dc=php,dc=net';
141
$options = array(
142
               'scope' => 'sub',        // all entries below the searchbase (recursive all subtrees from there)
143
               'attributes' => array('sn','gn','telephonenumber')  // what attributes to select
144
           );
145
$search = $ldap->search($searchbase, $filter, $options);
146
</pre>
147
$search should now be an Net_LDAP2_Search object.
148
<br>Okay, now we assume that everything was fine (in production, test for error!).
149
We have several options now.
150
We can fetch the found entries at once sorted ($search->sorted()) or unsorted ($search->entries()), or we can read
151
the objects one by one inside a loop using $search->shiftEntry(). See the class documentation of Net_LDAP2_Search
152
for more details.
153
</p>
154
 
155
<h2>Entries</h2>
156
<p>
157
This describes how to get an entry and modifying it.
158
If we just want one single entry, it may be useful to directly fetch that entry instead
159
of searching it manually. To do this you can use Net_LDAP2s "getEntry()" method:
160
<pre>
161
$dn = 'cn=Foo Bar,ou=dev,ou=People,dc=php,dc=net';
162
$entry =& $ldap->getEntry($dn, array('sn','gn','telephonenumber'));
163
</pre>
164
</p>
165
With this entry object you now can perform some actions like fetching the contents of attributes:
166
<pre>
167
$telephonenumber =    $entry->getValue('telephonenumber','single');
168
</pre>
169
Or you can modify a attribute:
170
<pre>
171
$entry->replace("telephonenumber" => "0123456789");   // replace the attributes values with the new number
172
$entry->update();  // update temporarily modified entry on the server
173
</pre>
174
Of course there are much more other possibilitys. Please note that adding and deleting
175
whole entrys is performed through the Net_LDAP2 class and not with the Net_LDAP2_Entry class.
176
 
177
<h2>Schemas</h2>
178
You may also use Net_LDAP2 to find out what schemas your ldap-server supports. Here's an example of how:
179
<pre>
180
$schema = $ldap->schema();
181
</pre>
182
Now you got a schemaobject.
183
To read from this schemaobject, you have several methods defined in the class Net_LDAP2_Schema.
184
<br>For example, to find out which attributes are required for inetOrgPerson, you do this:
185
<pre>
186
$required = $schema->must( 'inetOrgUser' );
187
 
188
print_r($required);
189
/* The output of this will be:
190
Array
191
(
192
     [0] => sn
193
     [1] => cn
194
)
195
*/
196
</pre>
197
 
198
Ok, but what kind of attribute is sn? Let's check:
199
<pre>
200
$att = $schema->get('attribute','sn');
201
 
202
print_r($att);
203
/* The output of this will be:
204
Array
205
(
206
     [aliases] => Array
207
             (
208
              [0] => surname
209
             )
210
 
211
     [oid] => 2.5.4.4
212
     [name] => sn
213
     [desc] => RFC2256: last (family) name(s) for which the entity is known by
214
     [sup] => Array
215
     (
216
        [0] => name
217
     )
218
     [type] => attribute
219
)
220
*/
221
</pre>
222
Hmm, ok, the sup part is important. It means that surname derives it's syntax from another attribute,
223
the name attribute. So , we need to check that as well.
224
<br>We do:
225
<pre>
226
$att_dep = $schema->get('attribute',$att['sup'][0]);
227
 
228
print_r($att_dep);
229
/* The output of this will be:
230
Array
231
(
232
    [aliases] => Array
233
        (
234
        )
235
 
236
    [oid] => 2.5.4.41
237
    [name] => name
238
    [desc] => RFC2256: common supertype of name attributes
239
    [equality] => caseIgnoreMatch
240
    [substr] => caseIgnoreSubstringsMatch
241
    [syntax] => 1.3.6.1.4.1.1466.115.121.1.15{32768}
242
    [max_length] => 32768
243
    [type] => attribute
244
)
245
*/
246
</pre>
247
From this we find out that the attribute has a maxlength of 32768 characters
248
and has the syntax 1.3.6.1.4.1.1466.115.121.1.15{32768}.