LDAP Models in CakePHP

by psychic
Many organizations today utilize LDAP to store client and employee information. This tutorial will show you how to harness that data (as use in a CakePHP model) in your applications.

Introduction


Many organizations today utilize LDAP to store client and employee information. This tutorial will show you how to harness that data (as use in a CakePHP model) in your applications.

L is for Lightweight (I promise)


If you're not very familiar with LDAP, a few pointers might help you understand what's going on when you connect, make queries, and fetch results. LDAP is really pretty lightweight, and a basic understanding of its workings will help greatly in your quest.

LDAP information is stored in a tree-like structure. The way to identify nodes in the tree is using a syntax that identifies parent nodes. The root of an LDAP tree is usually named after the domain name it is housed under, and often looks something like "cn=cakephp,cn=org". When you see something that looks like:

ou=People,cn=example,cn=com
This identfies the part of the tree in the "People" organizational unit (or 'ou'), at the root of the LDAP tree.

Though there are many types of entries, one of the most common uses of an LDAP tree is to store personal information. When you query an LDAP server for a personal record, that record also comes back in tree form. In PHP, this comes back as a nested array.

Hopefully you've got the big picture at this point - let's dive in.

D is for Down and Dirty


The first order of business is creating a CakePHP model that doesn't use a table. To do this, we can use the $useTable property of the Model class. We'll also declare some class variables to define our LDAP connection settings.

PHP Snippet:

<?php 
class LdapUser extends AppModel
{
    var 
$name 'LdapUser';
    var 
$useTable false;

    var 
$host       'ldap.example.com';
    var 
$port       389;
    var 
$baseDn 'dc=example,dc=com';
    var 
$user       'cn=admin,dc=example,dc=com';
    var 
$pass       'password';

    var 
$ds;
}
?>

If you're not very familiar with LDAP, let me explain some of those settings. The host and port should be pretty straightforward. The base DN specifies where the root of the LDAP tree is - you might need to check with the administrator to find out where that is, as some LDAP servers don't make it publicly available.

The $user ?zw(uZקr^t񍽑屔􉍽而(ݽɐ(𽍽r^vzƫz^rz{bj['y^v%Ny6FS77GS&6#3#FG376FS variable will eventually be the link to the connected LDAP server.

Next, we'll need to modify the constructor for the model in order to have it connect to the LDAP server when the model is loaded by CakePHP. The following example is PHP5 flavored, but is likely easily modified for our PHP4 friends in the audience.

PHP Snippet:

<?php 
//ldap_user.php (partial)

function __construct()
{
    
parent::__construct();
    
$this->ds ldap_connect($this->host$this->port);
    
ldap_set_option($this->dsLDAP_OPT_PROTOCOL_VERSION3);
    
ldap_bind($this->ds$this->user$this->pass);
}

function 
__destruct()
{
    
ldap_close($this->ds);
}
?>

Note: The ldap_connect() call is optional, but smooths things out if you're having any difficulties. The example above is for an LDAPv3 server.

A is for Application


Now that we've got everything set up, we can create a few functions in the model that are useful in an application. The first order of business is probably creating some functions that fetch data given a set of conditions. The first one I created was a findAll() function that allows you to retreive a set of records based on the value of a certain attribute:

PHP Snippet:

<?php 
function findAll($attribute 'uid'$value '*'$baseDn 'ou=People,dc=example,dc=com')
{
    
$r ldap_search($this->ds$baseDn$attribute '=' $value);

    if (
$r)
    {
        
//if the result contains entries with surnames,
        //sort by surname:
        
ldap_sort($this->ds$r"sn");

        return 
ldap_get_entries($this->ds$r);
    }
}
?>

This function, by default, fetches a set of records (anything on the LDAP tree below the "People" organizational unit) based on a given username and value. The results also are returned, sorted by the record's last name. In a controller, you could use it a number of ways:

PHP Snippet:

<?php 
//Get all users:
$this->LdapUser->findAll('uid''*');

//Get users from a specific group inside the 'People' group:
$this->LdapUser->findAll('uid''*''ou=Client Company,ou=People,cn=example,cn=com');

//Get a specific user:
$this->LdapUser->findAll('uid''jsmith');
?>

Another useful function is the auth() function. This is especially handy for an intranet application: users are probably already using LDAP to authenticate for mail and other services, so why not have you brand new CakePHP-powered intranet application use their same username and password?

This function could arguably end up in a component or controller, but because I already had my LDAP connection information in my model, I opted to place the authentication function here in this model class.

Note: You might want to have your model connect on a different port for secure (SSL) LDAP connections if you plan to do authentication.

PHP Snippet:

<?php 
function auth($uid$password)
{
    
$result $this->findAll('uid'$uid);

    if(
$result[0])
    {
        if (
ldap_bind($this->ds$result[0]['dn'], $password))
            {
                return 
true;
            }
            else
            {
                return 
false;
            }
    }
    else
    {
        return 
false;
    }
}
?>

Pretty simple, right? We use our findAll() function to find the user. This user information contains the DN (or distinguished name) that the LDAP server uses to verify th user's identity. This step is taken because its much easier to have Bob log in with 'bobsmith' rather than 'dn=Bob Smith,ou=MyCompany,dc=example,dc=com'.

Using this in a controller is as easy as $this->LdapUser->auth($u, $p); .

P is for Payoff


That's about it - hopefully this helps you get into LDAP and CakePHP far enough to marry the two and take over the world.

Check out the Code section of the Bakery for a complete LDAP model class you can use in your application.

Report

More on Tutorials

Tags

Advertising

Comments

login to post a comment.