Developer: PHP
Creating an LDAP Directory Service with PHP
Learn how to create a LDAP directory service in OID with PHP
Published December 2007
Oracle Internet Directory (OID)—an LDAP v3-compliant directory that leverages the scalability, high availability, and security features of Oracle Database—provides a directory service to store and modify information about network resources. (For example, OID serves as the central user repository for Oracle Identity Management.)
Many enterprise applications use the Java Naming and Directory Interface (JNDI) to access directory services in OID. When PHP-based Web applications are involved, however—and there are many millions of such apps, many with evolving security and authentication requirements—that method is obviously not an option. Instead, integrating PHP with OID can provide the required directory service.
In this article, you will learn how to use the PHP LDAP extension to create a directory service in OID. You will also add, modify, search, and delete a directory entry with the LDAP PHP class library.
Background
A directory service is an application/s that stores, retrieves and modifies information about network resources such as network users. The actual data is stored in a database; a directory service is an abstract layer on top of the database. Lightweight Directory Access Protocol (LDAP) is a lightweight protocol for accessing directory services; it also defines operations for adding, searching, modifying and deleting directory entries.
An "entry" is a set of attributes identified by a globally unique Distinguished Name (DN). Each directory entry's attribute has a type and one or more values. The attributes in a directory entry's DN are arranged in a hierarchy from right to left with the rightmost attribute as the top entry and with the leftmost attribute/s that are unique at its level called as Relative Distinguished Name (RDN).
A DN is a sequence of RDNs. Some examples of attribute types are discussed in Table 1.
Table 1. Attribute Types
| Attribute Type |
Description |
o |
Organization |
dc |
Domain component |
ou |
Organizational unit |
cn |
Common name |
uid |
Userid |
dn |
Distinguished name |
mail |
Email address |
Here's an example of a DN:
cn=dvohra,cn=PUBLIC,dc=example,dc=com
In this example, the base entry/root is dc=example,dc=com, and the RDN is cn=dvohra.
Installing PHP
Download the Apache HTTP Server 2.0. Install the Apache HTTP server by double-clicking on the Apache Web server application, apache_2.2.3-win32-x86-no_ssl.
Download PHP 5.2.5. Extract the PHP zip file php-5.2.5-Win32.zip to an installation directory, C:/PHP for example.
To the PATH environment system variable add C:/PHP, the directory in which PHP 5 is installed. Modify the php.init-recommended file in C:/PHP directory to php.ini.
Install PHP 5 in the Apache HTTP server. To the <Apache2>\conf\httpd.conf file add:
# For PHP 5
LoadModule php5_module "C:/PHP/php5apache2.dll"
AddType application/x-httpd-php .php
# configure the path to php.ini
PHPIniDir "C:/PHP/"
<Apache2> is the directory in which Apache 2 Web server is installed, and is C:\Program Files\Apache Software Foundation\Apache2.2 by default for Apache Http Server 2.2.3. For this tutorial, however, Apache 2 web server is installed in the C:/Apache2 directory. If the directory in which PHP 5 is installed is other than C:/PHP, replace C:/PHP with the directory in which PHP 5 is installed.
Installing Oracle Internet Directory
- Download Disk1 and Disk2 of the Oracle Identity Management Infrastructure and Oracle Identity Federation zip files.
- Extract disk1 to a directory. Extract disk2 zip file to the same directory as disk 1.
- To install Oracle Internet Directory click on the \install\setup application. The Oracle Universal Installer gets started.
- Click on Next.
- Specify the installation directory in the Specify File Locations frame and click on Next.

Figure 1
Select Oracle Application Server Infrastructure 10g and click on Next. The Oracle Application Server Infrastructure 10g includes OID and Oracle Database.

Figure 2
In the Select Installation Type frame select Identity Management and Metadata Repository, which installs the Oracle Internet Directory and Oracle Database 10g. Click on Next.

Figure 3
Select the default Oracle Application Server Infrastructure 10g components to install and click on Next.

Figure 4
Check the pre-installation requirements and click on Next. Select the default configuration options and click on Next.

Figure 5
Select the default port configuration options and click on Next.

Figure 6
Specify a namespace in the Oracle Internet Directory to create new users. For example, specify dc=example,dc=com and click on Next.

Figure 7
Specify database configuration options, or select the default database configuration options, and click on Next.

Figure 8
Specify database schema password and click on Next.

Figure 9
Specify an Oracle Application Server Infrastructure instance name. Specify a password for ias_admin administrator username and click on Next.

Figure 10
Click on Install to install the Oracle Application Server Infrastructure.

Figure 11
A dialog will prompt for the Oracle Application Server 10g disk 2. Specify the stage directory of disk2.

Figure 12
Next, the configuration assistants install.

Figure 13
Click on Next.

Figure 14
Click on Exit to complete the installation.

Figure 15
Next, start the Oracle Directory Manager, which is used to administer OID. Before you can use OID you need to start the OID Monitor and an OID server instance. Start the OID Monitor with the following command.
C:\>oidmon start
Start an Oracle Directory Server Instance with the following command.
C:\>oidctl server=oidldapd instance=2 start
Next, start the Oracle Directory Manager. In the Connect frame specify username as User as orcladmin, which is the superuser and specify the password as the password specified for the Oracle Application Server Infrastructure 10g instance. Specify Server as localhost and Port as 389, the default port. Click on Login.

Figure 16
The Oracle Directory Manager starts up.

Figure 17
Installing the PHP LDAP Extension
The PHP LDAP extension is not enabled by default. To enable the PHP LDAP extension remove the ';' before the following line in php.ini configuration file.
extension=php_ldap.dll
Copy the libeay32.dll and ssleay32.dll from the C:/PHP directory to the C:/WINNT/system32 directory. Restart Apache HTTP server.
The PHP LDAP class library provides various functions for creating an LDAP directory service. Some of the commonly used PHP LDAP functions are discussed in Table 2.
Table 2. PHP LDAP Functions
| Method |
Description |
ldap_connect ( [string hostname [, int port]] ) |
Connects to an LDAP server. If hostname is not specified, the link identifier of the already opened link is returned. Port defaults to 389. Returns a LDAP link identifier or FALSE if an error occurs. |
ldap_add ( resource link_identifier, string dn, array entry ) |
Adds a directory entry. Parameter link_identifier specifies the LDAP connection resource. Parameter dn specifies the dn of the directory entry. Parameter entry specifies an array of attributes in the directory entry. Returns TRUE if an add happens, FALSE if an error occurs. |
ldap_bind ( resource link_identifier [, string bind_rdn [, string bind_password]] ) |
Binds to an LDAP directory using the specified connection resource. Returns TRUE if bind happens, FALSE if an error occurs. |
ldap_unbind ( resource link_identifier ) |
Unbinds from a LDAP directory. Returns TRUE if an unbind happens, FALSE if an error occurs. |
ldap_close ( resource link_identifier ) |
Unbinds from a LDAP directory |
ldap_count_entries ( resource link_identifier, resource result_identifier ) |
Returns the number of entries in the LDAP search. Returns FALSE if an error occurs. |
ldap_delete ( resource link_identifier, string dn ) |
Deletes a directory entry |
ldap_error ( resource link_identifier ) |
Returns the error message of the last LDAP command |
ldap_get_attributes ( resource link_identifier, resource result_entry_identifier ) |
Returns an array attributes in a directory entry.
Returns FALSE if an error occurs |
ldap_first_entry ( resource link_identifier, resource result_identifier ) |
Returns the first entry in the result resource |
ldap_next_entry ( resource link_identifier, resource result_entry_identifier ) |
Returns the next entry in the result resource |
ldap_get_entries ( resource link_identifier, resource result_identifier ) |
Returns an array of entries in the result resource. |
ldap_get_dn ( resource link_identifier, resource result_entry_identifier ) |
Returns the dn of the result resource |
ldap_get_values ( resource link_identifier, resource result_entry_identifier, string attribute ) |
Returns all the attribute values for an attribute in result entry resource |
ldap_mod_add ( resource link_identifier, string dn, array entry ) |
Adds attribute values to attributes of a directory entry |
ldap_mod_del ( resource link_identifier, string dn, array entry ) |
Deletes attribute values from attributes of a dn |
ldap_mod_replace ( resource link_identifier, string dn, array entry ) |
Replaces attribute values for a dn |
ldap_modify ( resource link_identifier, string dn, array entry ) |
Modifies a directory entry |
ldap_search ( resource link_identifier, string base_dn, string filter [, array attributes [, int attrsonly [, int sizelimit [, int timelimit [, int deref]]]]] ) |
Searches a directory using the base dn, the specified filter and optionally an array of attributes. The filter specifies how the search is to be filtered, for example, only attributes for a particular objectclass may be searched. If only attribute types are required set attrsonly parameter to 1. The default value of attrsonly is 0. which fetches the attribute types and attribute values. The sizelimit parameter may be used to limit the number of entries returned. Sizelimit value 0 is equivalent to sizelimit not set. Parameter timelimit specifies the time limit in seconds for the search operation. |
Creating a Directory Entry
Next, create a directory entry in the OID LDAP server. For example, create a directory of JDeveloper developers. LDAP entries are represented in LDAP Data Interchange Format (LDIF) in a .ldif format. The format of an entry is as follows.
dn: <distinguished name>
<attrdesc>: <attrvalue>
<attrdesc>: <attrvalue>
dn represents the distinguished name for the directory entry and attrdesc/attrvalue represent attributes of the directory entry. We shall use the following dn as the root/base DN.
cn=PUBLIC,cn=Users,dc=example,dc=com
The directory node for the base dn is shown below . The selected dn supports top, person, organizationalPerson, inetorgperson, orcluser, and orcluserV2 object classes.

Figure 18
Each directory entry is identified with a dn attribute. The objectclass attribute specifies the type of data, and required and optional attributes in an entry. The objectclass attribute may have more than one value for the different object classes implemented by a directory entry. Object classes form a class hierarchy and some of the commonly used object classes are top, organization, and organizationalPerson. All object classes are sub classes of the object class 'top'. Each objectclass has required and optional attributes.
Now create a directory service with the top, person, organizationalPerson, inetorgperson, orcluser, and orcluserV2 object classes. The 'top' object class does not have any required attributes. Person object class required attributes are 'cn' and 'sn'. OrganizationalPerson, inetorgperson, orcluser, and orcluserV2 object classes do not have any required attributes. Some of the attributes that may specified in a directory entry of object class type organizationalPerson are title and telephoneNumber.
Create a PHP script, add_entry.php, in the C:\Apache2\htdocs directory. Start the OID LDAP server if not already started. First, create a connection with the OID server using the ldap_connect() function.
$ldaphost = "localhost";
$ldapport = 389;
$ldapconn = ldap_connect($ldaphost, $ldapport);
The ldap_connect() just initializes the connection parameters and returns a connection resource, but does not actually connect with the LDAP server. If the ldap_connect() method does not return error set the LDAP protocol version to 3 using LDAP_OPT_PROTOCOL_VERSION.
ldap_set_option($ldapconn, LDAP_OPT_PROTOCOL_VERSION, 3);
Next, bind to the LDAP server using the connection resource, username and password with the ldap_bind() function.
$r=ldap_bind($ldapconn," cn=orcladmin, "cn=PUBLIC,cn=Users,dc=example,dc=com","oid10admin");
To add a directory entry, create an entry consisting of an array of attributes. For example, the 'cn' attribute is specified as follows.
$directory_entry["cn"]="DeepakVohra";
In the example directory entry you shall be setting the attributes, cn, sn, title, telephoneNumber, physicalDeliveryOfficeName, and facsimileTelephoneNumber. If an attribute has more than 1 values the attribute values are specified using a 2-diminsional array. For example, the objectclass values are set as shown in following listing.
$directory_entry["objectclass"][0]="top";
$directory_entry["objectclass"][1]="person";
$directory_entry["objectclass"][2]="inetOrgPerson";
$directory_entry["objectclass"][3]="organizationalPerson";
$directory_entry["objectclass"][4]="orclUser";
$directory_entry["objectclass"][5]="orclUserV2";
Specify the dn of the directory entry to be added.
$dn="cn=DeepakVohra,cn=PUBLIC,cn=Users,dc=example,dc=com";
Add the directory entry to the LDAP directory using the ldap_add() method.
$r=ldap_add($ldapconn, $dn, $directory_entry);
The PHP script to add a directory entry, add_entry.php, is shown below.
<?php
$ldaphost = "localhost";
$ldapport = 389;
$ldapconn = ldap_connect($ldaphost, $ldapport);
if ($ldapconn) {
ldap_set_option($ldapconn, LDAP_OPT_PROTOCOL_VERSION, 3);
$r=ldap_bind($ldapconn,"cn=orcladmin","oid10admin");
if(!$r){echo "User did not bind to LDAP Server";}
else echo "User was bound to LDAP Server";
$directory_entry["cn"]="DeepakVohra";
$directory_entry["sn"]="Vohra";
$directory_entry["objectclass"][0]="top";
$directory_entry["objectclass"][1]="person";
$directory_entry["objectclass"][2]="inetOrgPerson";
$directory_entry["objectclass"][3]="organizationalPerson";
$directory_entry["objectclass"][4]="orclUser";
$directory_entry["objectclass"][5]="orclUserV2";
$directory_entry["title"]="PHP Developer";
$directory_entry["telephoneNumber"]="555 1234";
$directory_entry["physicalDeliveryOfficeName"]="JDeveloper";
$directory_entry["facsimileTelephoneNumber"]="555 5678";
$dn="cn=DeepakVohra,cn=PUBLIC,cn=Users,dc=example,dc=com";
$r=ldap_add($ldapconn, $dn, $directory_entry);
if(!$r) echo "Directory Entry not Added.";
else echo "Directory Entry Added";
ldap_close($ldapconn);
} else {
echo ldap_error($ldapconn);}
?>
Copy the PHP script, add_entry.php, to the C:\Apache2\htdocs directory. Run the PHP script with the URL http://localhost/add_entry.php. In the Oracle Directory Manager refresh the directory entries with View>Refresh.

Figure 19
A directory entry is added as shown in Oracle Directory Manager.

Figure 20
Modifying a Directory
In this section you will modify the directory entry that you added previously. Create a PHP script, modify_entry.php, to modify a directory entry.
First create a connection resource using the ldap_connect() method.
$ldaphost = "localhost";
$ldapport = 389;
$ldapconn = ldap_connect($ldaphost, $ldapport);
If a connection resource is created, set the LDAP protocol version to 3 and bind with the LDAP directory using the ldap_bind() function.
ldap_set_option($ldapconn, LDAP_OPT_PROTOCOL_VERSION, 3);
$r=ldap_bind($ldapconn,"cn=orcladmin","oid10admin");
Create an array of directory entry attributes with the modified values. For example, modify the 'title' attribute value and the physicalDeliveryOfficeName attribute value.
$directory_entry["title"]="Web Developer";
$directory_entry["physicalDeliveryOfficeName"]="Oracle JDeveloper";
Only the attributes to be modified are required to be specified in the attribute array.
A directory entry is identified with a distinguished name. Specify the dn of the directory entry to modify.
$dn="cn=DeepakVohra,cn=PUBLIC,cn=Users,dc=example,dc=com";
Modify the directory entry with the ldap_modify() function.
$r=ldap_modify($ldapconn,$dn, $directory_entry);
The PHP script, ldap_modify.php, to modify a directory entry is listed in Listing 2.
Listing 2. modify_entry.php
<?php
$ldaphost = "localhost";
$ldapport = 389;
$ldapconn = ldap_connect($ldaphost, $ldapport);
if ($ldapconn) {
ldap_set_option($ldapconn, LDAP_OPT_PROTOCOL_VERSION, 3);
$r=ldap_bind($ldapconn,"cn=orcladmin","oid10admin");
$directory_entry["title"]="Web Developer";
$directory_entry["physicalDeliveryOfficeName"]="Oracle JDeveloper";
$dn="cn=DeepakVohra,cn=PUBLIC,cn=Users,dc=example,dc=com";
$r=ldap_modify($ldapconn,$dn, $directory_entry);
if(!$r) echo "Directory Entry Not Modified";
else echo "Directory Entry Modified";
ldap_close($ldapconn);
} else {
echo ldap_error($ldapconn);
}
?>
Copy modify_entry.php to the C:\Apache2\htdocs directory.
Run the script with the URL http://localhost/modify_entry.php. The directory entry is modified as shown in the Oracle Directory Manager.

Figure 21
Searching a Directory
In this section you will use a PHTML (PHP embedded in HTML) script to search for a directory entry and display the result in HTML. Add the .phtml extension to the following Apache 2 configuration directive in C:/Apache2/conf/httpd.conf file.
AddType application/x-httpd-php .php .phtml
Restart the Apache 2 server. Create a PHTML script, search_entry.phtml, in the C:/Apache2/htdocs directory. First, create a connection resource for a LDAP server connection using the ldap_connect() method.
$ldaphost = "localhost";
$ldapport = 389;
$ldapconn = ldap_connect($ldaphost, $ldapport);
If a connection resource gets created, set the LDAP protocol version to 3 and with the directory server using the ldap_bind() method.
ldap_set_option($ldapconn, LDAP_OPT_PROTOCOL_VERSION, 3);
$r=ldap_bind($ldapconn,"cn=orcladmin","oid10admin");
Next, specify an attribute array for which attribute values are to be retrieved. By default, all the attributes are retrieved.
$attribute_array=array("cn", "sn", "title", "telephoneNumber","physicalDeliveryOfficeName",
"facsimileTelephoneNumber", "objectclass");
Specify the dn of the directory entry to search.
$dn="cn=DeepakVohra,cn=PUBLIC,cn=Users,dc=example,dc=com";
Specify a filter for the search. For example, specify a filter that searches for all objectclasses.
$filter = "(objectclass=*)";
Search the directory using the ldap_search() method.
$sr=ldap_search($ldapconn,$dn, $filter, $attribute_array);
Retrieve the directory entries in the search result using the ldap_get_entries() method.
$directory_entries= ldap_get_entries($ldapconn, $sr);
Create an HTML table to display the search result. Add a header row to the table. Retrieve the value/s of each attribute and add the value to the table. The directory entries search result is an array of entries. The first directory entry is accessed with the expression $directory_entries[0].
A directory entry consists of an array of attributes. An attribute in a directory entry is accessed by specifying the attribute name in the attribute array. (For example, the 'cn' attribute is accessed with the expression $directory_entries[0]['cn'].)
An attribute consists of an array of values; an array value is accessed by specifying the attribute values array index. The objectclass attribute has multiple values. For example, the first value in the objectclass attribute values array is accessed with the expression $directory_entries[0]['objectclass'][0]. The number of attribute values in an array may be obtained with the "count" property. For example, the number of values of the objectclass attribute is obtained as follows.
$count=$directory_entries[0]['objectclass']["count"];
Retrieve attribute values from the search result and add to the table. For example the 'cn' attribute row is added as shown below.
<tr><td>cn</td><td><?php echo $directory_entries[0]['cn'][0]; ?></td></tr>
If an attribute has more than one value, as the objectclass attribute does, use the for () loop to iterate over the attribute values and output the attribute values.
for ($i=0; $i<$count; $i++){
print $directory_entries[0]['objectclass'][$i]."<br>";
}
The search_entry.phtml script is listed in Listing 3.
Listing 3. search_entry.phtml
<?php
$ldaphost = "localhost";
$ldapport = 389;
$ldapconn = ldap_connect($ldaphost, $ldapport);
if ($ldapconn) {
ldap_set_option($ldapconn, LDAP_OPT_PROTOCOL_VERSION, 3);
$r=ldap_bind($ldapconn,"cn=orcladmin","phpldap");
$attribute_array=array("cn", "sn", "title", "telephoneNumber",
"physicalDeliveryOfficeName","facsimileTelephoneNumber",
"objectclass");
$dn="cn=DeepakVohra,cn=PUBLIC,cn=Users,dc=example,dc=com"; $filter = "(objectclass=*)";
$sr=ldap_search($ldapconn,$dn, $filter, $attribute_array);
$directory_entries= ldap_get_entries($ldapconn, $sr);
ldap_close($ldapconn);
} else {
echo ldap_error($ldapconn);}
?>
<HTML>
<HEAD>
<TITLE> Directory Entry</TITLE>
</HEAD
<BODY>
<p> </p>
<table border>
<tr><th>Attribute</th><th>Value</th></tr>
<tr><td>cn</td><td><?php echo $directory_entries[0]['cn'][0]; ?></td></tr>
<tr><td>sn</td><td><?php print $directory_entries[0]['sn'][0]; ?></td></tr>
<tr><td>title</td><td><?php print $directory_entries[0]['title'][0]; ?></td></tr>
<tr><td>telephoneNumber</td><td>
<?php print $directory_entries[0]['telephonenumber'][0]; ?></td></tr>
<tr><td>physicalDeliveryOfficeName</td><td>
<?php print $directory_entries[0]['physicaldeliveryofficename'][0]; ?></td></tr>
<tr><td>facsimileTelephoneNumber</td><td>
<?php print $directory_entries[0]['facsimiletelephonenumber'][0]; ?></td></tr>
<tr><td>objectclass</td><td>
<?php
$count=$directory_entries[0]['objectclass']["count"];
for ($i=0; $i<$count; $i++){
print $directory_entries[0]['objectclass'][$i]."<br>";
}
?></td></tr>
</table>
</BODY>
</HTML>
Run the search_entry.phtml script with the URL http://localhost/search_entry.phtml to search for a directory entry. The directory entry attributes are displayed.

Figure 22
Deleting a Directory
In this section, you will delete a directory entry. Create a PHP script, delete_entry.php, in the C:/Apache2/htdocs directory. First, obtain a connection resource with the LDAP server using the ldap_connect() method.
$ldaphost = "localhost";
$ldapport = 389;
$ldapconn = ldap_connect($ldaphost, $ldapport);
If a connection resource gets created set the LDAP protocol version to 3 and bind with the ldap_bind() function.
ldap_set_option($ldapconn, LDAP_OPT_PROTOCOL_VERSION, 3);
$r=ldap_bind($ldapconn,"cn=orcladmin","oid10admin");
Specify the dn of the directory entry to delete.
$dn="cn=DeepakVohra,cn=PUBLIC,cn=Users,dc=example,dc=com";
Delete the directory entry using the ldap_delete() method.
$r=ldap_delete($ldapconn, $dn);
The PHP script delete_entry.php is listed in Listing 4.
Listing 4. delete_entry.php
<?php
$ldaphost = "localhost";
$ldapport = 389;
$ldapconn = ldap_connect($ldaphost, $ldapport);
if ($ldapconn) {
ldap_set_option($ldapconn, LDAP_OPT_PROTOCOL_VERSION, 3);
$r=ldap_bind($ldapconn,"cn=orcladmin","oid10admin");
$dn="cn=DeepakVohra,cn=PUBLIC,cn=Users,dc=example,dc=com";
$r=ldap_delete($ldapconn, $dn);
if(!$r) echo "Directory Entry Not Deleted";
else echo "Directory Entry Deleted";
ldap_close($ldapconn);
} else {
echo ldap_error($ldapconn);
}
?>
To delete a directory entry invoke the delete_entry.php script with the URL http://localhost/delete_entry.php. The directory entry is deleted as shown in the Oracle Directory Manager.

Figure 23
Congratulations, you have learned how to create and delete an LDAP directory service in OID with PHP.
Deepak Vohra (dvohra09@yahoo.com) is a Sun Certified Java Programmer, a NuBean consultant, and has been published in onjava.com, XML Journal, WebLogic Developer's Journal, and OTN.
|