<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>Random Tech Articles &#187; CakePHP</title>
	<atom:link href="http://www.analogrithems.com/rant/tag/cakephp/feed/" rel="self" type="application/rss+xml" />
	<link>http://www.analogrithems.com/rant</link>
	<description>If I have seen a little further it is by standing on the shoulders of Giants. - Newton</description>
	<lastBuildDate>Thu, 02 Feb 2012 20:07:05 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.3.1</generator>
<xhtml:meta xmlns:xhtml="http://www.w3.org/1999/xhtml" name="robots" content="noindex" />
		<item>
		<title>LdapAuth component for CakePHP</title>
		<link>http://www.analogrithems.com/rant/2009/06/13/ldapauth-component-for-cakephp/</link>
		<comments>http://www.analogrithems.com/rant/2009/06/13/ldapauth-component-for-cakephp/#comments</comments>
		<pubDate>Sat, 13 Jun 2009 22:08:52 +0000</pubDate>
		<dc:creator>analogrithems</dc:creator>
				<category><![CDATA[CakePHP]]></category>
		<category><![CDATA[Featured]]></category>
		<category><![CDATA[ldap]]></category>
		<category><![CDATA[centralized authentication]]></category>

		<guid isPermaLink="false">http://www.analogrithems.com/rant/?p=40</guid>
		<description><![CDATA[So I was looking for a way to authenticate against LDAP with cake but I&#8217;ve found that it doesn&#8217;t support it by default. I found one that checks the auth against ldap then creates a local mysql account. This also &#8230; <a href="http://www.analogrithems.com/rant/2009/06/13/ldapauth-component-for-cakephp/">Continue reading <span class="meta-nav">&#8594;</span></a>]]></description>
			<content:encoded><![CDATA[<a href='http://twitter.com/share?url=http%3A%2F%2Fwww.analogrithems.com%2Frant%2F%3Fp%3D40&count=horizontal&related=&text=LdapAuth%20component%20for%20CakePHP' class='twitter-share-button' data-text='LdapAuth component for CakePHP' data-url='http://www.analogrithems.com/rant/?p=40' data-counturl='http://www.analogrithems.com/rant/2009/06/13/ldapauth-component-for-cakephp/' data-count='horizontal' data-via='analogrithems'></a><p>So I was looking for a way to authenticate against LDAP with cake but I&#8217;ve found that it doesn&#8217;t support it by default.  I found one that checks the auth against ldap then creates a local mysql account.  This also didn&#8217;t use a actual ldap data sourc e either, it just handeled it&#8217;s own ldap connection.  After I read through the standard cakphp auth component I saw that it wouldn&#8217;t be that hard to write an LDAP based auth component.</p>
<p>First you need to download this file <a href="http://www.analogrithems.com/rant/wp-content/uploads/2009/06/ldap_auth.phps">ldap_auth.php</a> to your <strong>&#8216;app/controllers/components/&#8217;</strong> directory.</p>
<p>Then just like the original auth component you add that component to a model.  I followed the usual auth example and created a model called Users.php like so</p>
<pre lang="php">
<?php
class User extends AppModel {
	var $name = 'User';
	var $useDbConfig = 'ldap';
	var $primaryKey = 'uid';
	var $useTable = 'ou=people';
}
?>
</pre>
<p>If some of these options are odd looking please have a look at my <a href="http://www.analogrithems.com/rant/?p=3">ldap data source </a> post.  </p>
<p>Next you are going to need your controller.  Here is the one I used  It defines the required functions like login, logout &#038; authorize. </p>
<pre lang="php">
<?php
class UsersController extends AppController {

	var $name = 'Users';
        var $components = array('RequestHandler', 'LdapAuth');
        var $helpers = array('Form','Html','Javascript', 'Ajax');

	function login() {
	}

	function logout() {
		$this->redirect($this->LdapAuth->logout());
	}

        function isAuthorized() {
                return true;
        }

}
?>
</pre>
<p>7</p>
<p class="facebook"><a href="http://www.facebook.com/share.php?u=http://www.analogrithems.com/rant/2009/06/13/ldapauth-component-for-cakephp/" target="_blank" title="Share on Facebook">Share on Facebook</a></p>]]></content:encoded>
			<wfw:commentRss>http://www.analogrithems.com/rant/2009/06/13/ldapauth-component-for-cakephp/feed/</wfw:commentRss>
		<slash:comments>18</slash:comments>
		</item>
		<item>
		<title>CakePHP: LDAP with full CRUD, a living example!</title>
		<link>http://www.analogrithems.com/rant/2009/06/12/cakephp-with-full-crud-a-living-example/</link>
		<comments>http://www.analogrithems.com/rant/2009/06/12/cakephp-with-full-crud-a-living-example/#comments</comments>
		<pubDate>Fri, 12 Jun 2009 22:14:35 +0000</pubDate>
		<dc:creator>analogrithems</dc:creator>
				<category><![CDATA[CakePHP]]></category>
		<category><![CDATA[Featured]]></category>
		<category><![CDATA[ldap]]></category>

		<guid isPermaLink="false">http://www.analogrithems.com/rant/?p=13</guid>
		<description><![CDATA[I&#8217;ve been using CakePHP for a while now and I&#8217;ve been thinking for a while it was time to see if I could give something back. As an IT leader I&#8217;m in love with LDAP. It makes life so simple &#8230; <a href="http://www.analogrithems.com/rant/2009/06/12/cakephp-with-full-crud-a-living-example/">Continue reading <span class="meta-nav">&#8594;</span></a>]]></description>
			<content:encoded><![CDATA[<a href='http://twitter.com/share?url=http%3A%2F%2Fwww.analogrithems.com%2Frant%2F%3Fp%3D13&count=horizontal&related=&text=CakePHP%3A%20LDAP%20with%20full%20CRUD%2C%20a%20living%20example%21' class='twitter-share-button' data-text='CakePHP: LDAP with full CRUD, a living example!' data-url='http://www.analogrithems.com/rant/?p=13' data-counturl='http://www.analogrithems.com/rant/2009/06/12/cakephp-with-full-crud-a-living-example/' data-count='horizontal' data-via='analogrithems'></a><p><span>I&#8217;ve been using <span>CakePHP</span> for a while now and I&#8217;ve been thinking for a while it was time to see if I could give something back.  As an IT leader I&#8217;m in love with LDAP.  It makes life so simple for me and my team.  The big downside to LDAP is it&#8217;s not very easy to learn how all the <span>objectClasses</span> and attributes work with various applications.  Microsoft has eliminated this with the </span><em>Microsoft Management Console</em> (<em>MMC</em><span>).   It amazes me that no open source project has developed a tools such as this before.  I&#8217;ve worked on a open source tool in the past that was a web interface wrapper around <span>ldap</span> to do account management, so I&#8217;m familiar with the requirements such an application should have. Being that <span>CakePHP</span> is so powerful, I wanted to see if I could do this with that.</span></p>
<p><span>When I first started, I realized that <span>CakePHP</span> didn&#8217;t have an LDAP data source officially supported yet.  I did find two articles about some good attempts.  One by </span><a href="http://bakery.cakephp.org/articles/view/ldap-datasource-for-cakephp" target="_blank"><span><span><span>euphrate</span></span></span></a><span>, unfortunately this one was only for reading from <span>ldap</span>.  The second one was by </span><a href="http://memdump.wordpress.com/2008/04/26/ldap-data-source-now-with-full-crud/"><span><span>Gservat</span></span></a><span>, this one was a bit more complete, but was not really working for me and  as i read from his comments many others.  I think we wrote his for <span>CakePHP</span> 1.1.  Since I wanted to use Current cake 1.2.8xxx  I set out to use this as my start and fix/extend it.</span></p>
<p><span>Before we get started I want to state the environment I was using to do my work was <span>Redhat</span> Enterprise 5.2 &amp; Fedora 10 (Work requirement) with <span>redhat</span> directory server 8.1 and Fedora directory server 1.2.  Now while LDAP is a standard protocol, some of the driver may have become centric to those platforms, so if this is the case, please leave me a comment and I will try to correct the <span>ldap</span> data source I&#8217;m working on.  My hope is to get <span>ldap</span> as an <span>offical</span> <span>CakePHP</span> data source.  With that said the reason i call this a living example is because I&#8217;ve continued to upgrade and improve this data source as well as this article.  Some of the next features I want to implement is data associations.  Basically has and belongs to many relations.  This way when y<span>ou</span> look up an user account it also shows y<span>ou</span> all the groups that user is in.  This will take some time but I&#8217;ll get there.  This work is all being done in the hopes that I can use this data source and <span>CakePHP</span> to build a really user friendly web interface for managing enterprise LDAP infrastructures without a whole lot of LDAP knowledge.</span></p>
<p><strong><span>6/1/2011 &#8211; This <span>datasource</span> has gotten picked up by the <span>CakePHP</span> core guys and they may be </span><span>officially</span> adding it in the future.  I&#8217;ve also added some changes to support Active Directory better.</strong></p>
<p><strong><span>4/15/2010 &#8211; Made several changes to the code to hopefully play nicely with active directory.  Tested it with <span>CakePHP</span>-1.3 everything looks good.  Please test and leave feedback.  The new <span>datasource</span> requires y<span>ou</span> to add a new field to the database.<span>cfg</span> <span>ldap</span> entry.  See the <span>config</span> below</span><br />
</strong></p>
<p><strong><span>8/20/2009 &#8211; New Home for the source.  I&#8217;ve got this <span>datasource</span> in my  <span>github</span> tree now </span><a href="http://github.com/analogrithems/idbroker/tree/master/models/datasources"><span>http://<span>github</span>.com/<span>analogrithems</span>/<span>idbroker</span>/tree/master/models/<span>datasources</span></span></a> enjoy, and feel free to submit bugs or request there.</strong></p>
<p><strong><span>7/13/2009 &#8211; updated <span>ldap</span>_source.<span>php</span> to make better use of the debug describe code.  Also fixed the way things update.  Only update what has changed instead of whole record.  This will help with LDAP <span>aci</span> rules when logging in as non-admin users and trying to do things like update your <span>userpassword</span> or email.</span></strong></p>
<p><strong><span>6/20/2009 &#8211; Updated <span>ldap</span>_source.<span>php</span> to work with <span>OpenLDAP</span> 2.3 schema system.  First it will try &#8216;<span>cn</span>=schema&#8217;, if that doesn&#8217;t return any results then it looks for <span>schemas</span> in &#8216;<span>cn</span>=subschema&#8217;  this make sure the code will work with <span>OpenLDAP</span> as well as the Netscape based versions like <span>iPlanet</span>, <span>Redhat</span> Directory Server, Fedora Directory Server etc.</span></strong></p>
<p><span>First things first, here is my <span>ldap</span> data source for <span>CakePHP</span>.  Y<span>ou</span> will need to download this </span><a href="http://www.analogrithems.com/rant/wp-content/uploads/2009/07/ldap_source.phps" target="_blank"><span><span>ldap</span>_source.<span>php</span></span></a><span> to your &#8216;app/models/<span>datasources</span>/&#8217; directory.</span></p>
<p><span>So lets dive right in below is the database <span>config</span> we will use.</span></p>
<pre class="brush: php; title: ; notranslate">
&lt;?php
class DATABASE_CONFIG {
var $ldap = array (
 		'datasource' =--&gt; 'ldap',
		'host' =&gt; 'localhost',
		'port' =&gt; 389,
		'basedn' =&gt; 'dc=examnple,dc=com',
		'login' =&gt; '',
		'password' =&gt; '',
		'database' =&gt; '',
                'tls'         =&gt; false,
                'type' =&gt; 'Netscape', //Available types are 'OpenLDAP', 'ActiveDirectory', 'Netscape'
		'version' =&gt; 3
	);
}
?&gt;
</pre>
<p><span>Y<span>ou</span> notice that the variables database, <span>login</span> and password are blank.  Keep at least database this way.  Y<span>ou</span> can populate <span>login</span> and password if don&#8217;t want your <span>ldap</span> connections to be anonymous.  I keep mine blank because I have written my own <span>auth</span> component that uses <span>ldap</span>,   So once I&#8217;m <span>authed</span> that gets passed to the <span>datasource</span> instead.  This is a ugly hack that I&#8217;ve written another </span><a href="http://www.analogrithems.com/rant/2009/06/13/ldapauth-component-for-cakephp/">post about</a>.</p>
<p><span>Please note that if y<span>ou</span> are using <span>Redhat</span> directory server, <span>iPlanet</span> or Fedora Project 389 then the </span><strong>type</strong> is Netscape as these all evolved off the Netscape LDAP server code base.  The other available types are &#8216;OpenLDAP&#8217; or &#8216;ActiveDirectory&#8217;  (case matters).</p>
<p>Here is our people model for accessing the users in your LDAP tree.</p>
<pre class="brush: php; title: ; notranslate">
&lt;?php
class Person extends AppModel {
        var $name = 'Person';
        var $useDbConfig = 'ldap';

        // This would be the ldap equivalent to a primary key if your dn is
        // in the format of uid=username, ou=people, dc=example, dc=com
        var $primaryKey = 'uid';

        // The table would be the branch of your basedn that you defined in
        // the database config
        var $useTable = '';

        var $validate = array(
                'cn' =&gt; array(
                        'alphaNumeric' =&gt; array(
                                'rule' =&gt; array('custom', '/^[a-zA-Z ]+$/'),
                                'required' =&gt; true,
                                'on' =&gt; 'create',
                                'message' =&gt; 'Only Letters, Numbers and spaces	 can be used for Display Name.'
                        ),
                        'between' =&gt; array(
                                'rule' =&gt; array('between', 5, 40),
                                'on' =&gt; 'create',
                                'message' =&gt; 'Between 5 to 40 characters'
                        )
                ),
                'sn' =&gt; array(
                                'rule' =&gt; array('custom', '/^[a-zA-Z]*$/'),
                                'required' =&gt; true,
                                'on' =&gt; 'create',
                                'message' =&gt; 'Only Letters and Numbers can be used for Last Name.'
                ),
                'userpassword' =&gt; array(
                                'rule' =&gt; array('minLength', '8'),
                                'message' =&gt; 'Mimimum 8 characters long.'
                ),
                'uid' =&gt; array(
                                'rule' =&gt; array('custom', '/^[a-zA-Z0-9]*$/'),
                                'required' =&gt; true,
                                'on' =&gt; 'create',
                                'message' =&gt; 'Only Letters and Numbers can be used for Username.'
                )
        );
}
?&gt;
</pre>
<p>Here is a very basic controller to accompany our people model.  It demonstrates the important core functions and should get you started on using this data source with your own application.</p>
<pre class="brush: php; title: ; notranslate">
&lt;?php
class PeopleController extends AppController {

	var $name = 'People';
	var $components = array('RequestHandler', 'Ldap');
	var $helpers = array('Form','Html','Javascript', 'Ajax');

	function add(){
		if(!empty($this-&gt;data)){
			$this-&gt;data['Person']['objectclass'] = array('top', 'organizationalperson', 'inetorgperson','person','posixaccount','shadowaccount');

			if($this-&gt;data['Person']['password'] == $this-&gt;data['Person']['password_confirm']){
				$this-&gt;data['Person']['userpassword'] = $this-&gt;data['Person']['password'];
				unset($this-&gt;data['Person']['password']);
				unset($this-&gt;data['Person']['password_confirm']);

				if(!isset($this-&gt;data['Person']['homedirectory'])&amp;&amp; isset($this-&gt;data['Person']['uid'])){
					$this-&gt;data['Person']['homedirectory'] = '/home/'.$this-&gt;data['Person']['uid'];
				}

				$cn = $this-&gt;data['Person']['cn'];
				if ($this-&gt;Person-&gt;save($this-&gt;data)) {
					$this-&gt;Session-&gt;setFlash($cn.' was added Successfully.');
					$id = $this-&gt;Person-&gt;id;
					$this-&gt;redirect(array('action' =&gt; 'view', 'id'=&gt; $id));
				}else{
					$this-&gt;Session-&gt;setFlash(&quot;$cn couldn't be created.&quot;);
				}
			}else{
				$this-&gt;Session-&gt;setFlash(&quot;Passwords don't match.&quot;);
			}
		}
		$attributes = array('uidnumber', 'uid', 'homedirectory');
		$preset = $this-&gt;autoSet($attributes);
		foreach($this-&gt;data['Person'] as $key =&gt; $value){
			$preset[$key] = $value;
		}
		$this-&gt;data['Person'] = $preset;

		$groups = $this-&gt;Ldap-&gt;getGroups(array('cn','gidnumber'),null,'posixgroup');
		foreach($groups as $group){
			$groupList[$group['gidnumber']] = $group['cn'];
		}
		natcasesort($groupList);
		$this-&gt;set('groups',$groupList);
		$this-&gt;layout = 'people';
	}

	function view( $id ){
		if(!empty($id)){
			$filter = $this-&gt;Person-&gt;primaryKey.&quot;=&quot;.$id;
			$people = $this-&gt;Person-&gt;find('first', array( 'conditions'=&gt;$filter));
			$this-&gt;set(compact('people'));
		}
		$this-&gt;layout = 'people';
	}

	function delete($id = null) {
		$this-&gt;Person-&gt;id = $id;
		return $this-&gt;Person-&gt;del($id);
	}

	/**
	*  The AuthComponent provides the needed functionality
	*  for login, so you can leave this function blank.
	*/
	function login() {
	}

	function logout() {
		$this-&gt;redirect($this-&gt;LdapAuth-&gt;logout());
	}

	//Very Ugly, fix this.,
	function isAuthorized() {
		return true;
	}

}
</pre>
<p>So lets talk about somethings here,  in our model we define <strong><span>$<span>primaryKey</span></span></strong> &amp; <strong><span>$<span>useTable</span></span></strong> variables.  The <strong><span>$<span>useTable</span></span></strong><span> is the branch of the <span>ldap</span> server.  For this models purpose we define our table as </span><strong>&#8216;ou=people&#8217;</strong>.  This makes sure that objects we create (I.E. Users/people)  will be added under the organization unit people.  It also makes sure that when you pass something like &#8216;jdoe&#8217; to the delete action it will search that branch for the user object to delete.  The <strong><span>$<span>primaryKey</span></span></strong><span> also helps in the creation and deleting of users.  It makes sure that the <span>dn</span> is created as <span>uid</span>, this is helpful to make sure that a user doesn&#8217;t already have that user name.  Also since <span>ldap</span> is case insensitive y<span>ou</span> don&#8217;t have to worry about the possible variations of the object names when checking the existence.</span></p>
<p>Now your model isn&#8217;t limited to one branch or object type.  If you wanted to create a browser for example your could define a model like the following.</p>
<p>You&#8217;ll notice here we set our <strong><span>$<span>useTable</span></span></strong><span> to nothing (important, y<span>ou</span> get errors about no db defined from <span>CakePHP</span> if this missing).  The really interesting part here is that we set </span><strong>$primaryKey</strong><span> to <span>dn</span>.  This is the ultimate primary key for our type or data source.  The difference here is that when we create/delete an object we have to pass it the full <span>dn</span>.</span></p>
<p>Our new data source also adds some new options to the find function.<br />
<strong>$options['targetDN'] :</strong><span> This is more like the point in the tree we want to start our search.  If y<span>ou</span> don&#8217;t define it it defaults to the $<span>useTable</span>.$<span>config</span>[$<span>useDbConfig</span>]['basedn']  if your $<span>useTable</span> variable is empty it defaults to the <span>basedn</span> configured in your database <span>config</span>.</span></p>
<p><strong>$options['scope'] :</strong><span> If you&#8217;ve worked with <span>ldap</span> before then y<span>ou</span> are familiar with the concept of search scopes.  Y<span>ou</span> have three search scopes, &#8216;sub&#8217;, &#8216;one, &amp; &#8216;base&#8217;.  Basically </span><strong>sub</strong> means search from this point down the tree.  <strong>one</strong> means search one level below this point and <strong>base</strong><span> means search just this point.  For example if y<span>ou</span> wanted to see if a user already existed y<span>ou</span> could set the targetDn to <span>uid</span>=<span>jdoe</span>,<span>ou</span>=people,dc=example,dc=com and it will check if this object already exists.   The default scope is </span><strong>sub</strong></p>
<p class="facebook"><a href="http://www.facebook.com/share.php?u=http://www.analogrithems.com/rant/2009/06/12/cakephp-with-full-crud-a-living-example/" target="_blank" title="Share on Facebook">Share on Facebook</a></p>]]></content:encoded>
			<wfw:commentRss>http://www.analogrithems.com/rant/2009/06/12/cakephp-with-full-crud-a-living-example/feed/</wfw:commentRss>
		<slash:comments>60</slash:comments>
		</item>
	</channel>
</rss>

<!-- Performance optimized by W3 Total Cache. Learn more: http://www.w3-edge.com/wordpress-plugins/

Minified using disk: basic

Served from: www.analogrithems.com @ 2012-02-05 02:02:42 -->
