November 8, 2007 16

Secure CakePHP via Sessions & Magic (Login / Logout)

CakePHP

Making sure a CakePHP application is secure is a total snap thanks to “sessions” – the rock animal of websites. Put on your All-Stars and boot up your MacBook – I’m about to go Discovery Channel on your ass.

Hopefully by the end of reading this article, you’ll be able to create a secure CakePHP application. The point is to allow only registered users access to restricted areas of your application without blocking access to all areas of your application.

Pretext

We’ll be creating three sections in order to achieve our goal of total security:

1: /app/app_controller.php
2: /app/controllers/users_controller.php
3: /app/views/users/
      -> add.thtml, edit.thtml, index.thtml, login.thtml, logout.thtml

As always, all of these sections can be downloaded so you can follow along.

1. The app_controller

Our app_controller.php file will hold the function checkSession which will check session data to make sure a user is logged in. Here’s the function in its entirety:

function checkSession(){

	// fill $username with session data
	$username = $this->Session->read('user');

	// if the $username is empty,
	// send user to login page
	if (!$username){
		$this->redirect('/users/login');
		exit();
	} else {
		// if $username is not empty,
		// check to make sure it's correct
		$results = $this->User->findByEmail($username);

		// if not correct, send to login page
		if(!$results){
			$this->Session->delete('user');
			$this->Session->setFlash('Incorrect session data.');
			$this->redirect('/users/login');
			exit();
		}

		// otherwise set $user variable as users email address
		$this->set('user', $results['User']['email']);
	}
}
/pre>

The commenting throughout the above code is pretty self-explanatory - the session data is checked and validated. Score one for us.

2. The users_controller

Of the six functions in users_controller.php, we'll cover the login function. It's purpose is to check user-submitted data against a database, and either set a session (success) or redirect the user to the login page (failure) for another login attempt.
function login() {
	$this->set('error', false);
	if ($this->data) {
		// check submitted email address against database
		$results = $this->User->findByEmail($this->data['User']['email']);
		if ($results && $results['User']['password'] == md5($this->data['User']['password'])) {
			// set "user" session equal to email address
			$this->Session->write('user', $this->data['User']['email']);
			// set "last_login" session equal to users last login time
			$this->Session->write('last_login', $results['User']['last_login']);
			$results['User']['last_login'] = date("Y-m-d H:i:s");
			// save last_login date
			$this->User->save($results);
			$this->redirect('/');
		} else {
			// login data is wrong, redirect to login page
			$this->Session->setFlash('Wrong username / password. Please try again.');
			$this->redirect('/users/login');
		}
	}
}

The commented code above should be enough to grasp an understanding of how $this->Session works. It's a simple CakePHP method of setting/deleting/reading sessions.

Secure Your Gear

Now that you've got the code to secure your Cake pages, you need to use it. Call the checkSession function to whenever you'd like to require a user to be logged in.

// make sure we're logged in
		$this->checkSession();

		// when viewing /app/views/examples/index.thtml
		// the user will be redirected to the login page
		// unless he's logged in, in which case he'll
		// see the page as normal
	}

	function example() {
		// when viewing /app/views/examples/example.thtml
		// everyone (logged in or not) will see this page
	}
}	

But what if you want to secure all the pages in a controller? Simple! Use Cake's beforeFilter function:

checkSession();
	}

	function index() {
		// when viewing /app/views/examples/index.thtml
		// the user will be redirected to the login page
		// unless he's logged in, in which case he'll
		// see the page as normal
	}

	function example() {
		// when viewing /app/views/examples/example.thtml
		// the user will be redirected to the login page
		// unless he's logged in, in which case he'll
		// see the page as normal
	}
}

Download The Package

Make sure you grab the complete package to see working examples of this article. A .sql file has been included for easy setup of the required MySQL users table.

Download the 'Secure CakePHP via Sessions' package and consider yourself cool.

16 Responses to “Secure CakePHP via Sessions & Magic (Login / Logout)”

  1. Martin says:

    maybe you could a little plugin with it :)
    http://manual.cakephp.org/chapter/plugins

  2. Brad says:

    More fine-grained control can be obtained using ACL, which is described in the cake manual (applicable to 1.1) and numerous tutorials (1.1 & 1.2, YMMV).

  3. Chris says:

    Thanks a lot man, works like a charm :)

  4. Jay says:

    It works very well! :) Thanks

  5. Hi,

    is this also running on cakephp 1.2 version?

  6. Gaz says:

    Yes this works on cakephp 1.2

  7. karim says:

    You should add some salt to the md5 :)

    
    if ($results && $results['User']['password'] == md5($this->data['User']['password'].'somesalt'))
    

    and add ‘somesalt’ when you create the user’s record (add action for eg.)

  8. jdm says:

    I am still a beginner of this,i find difficulty in understanding it..
    I downloaded the package but errors are coming out..Please help me with this.

    Please explain me why are there errors? What’s wrong with this?

    
    Errors:
    - Warning (512): Method HtmlHelper::formTag does not exist [CORE/cake/libs/view/helper.php, line 148]
    - Warning (512): Method HtmlHelper::inputTag does not exist [CORE/cake/libs/view/helper.php, line 148]
    - Notice (1024): Method tagErrorMsg() is deprecated in HtmlHelper: see FormHelper::error [CORE/cake/libs/view/helpers/html.php, line 801]
    - Warning (512): Method HtmlHelper::passwordTag does not exist [CORE/cake/libs/view/helper.php, line 148]
    - Warning (512): Method HtmlHelper::submitTag does not exist [CORE/cake/libs/view/helper.php, line 148]
    
  9. Javier says:

    The code works very well, thanks a lot!

  10. dave says:

    jdm,

    I’m not sure, but it seems like you are using the wrong version of CakePHP. There are certain tasks that were moved from the html helper to the form helper, I am a beginner too so I may be 100% wrong, but those warnings look like the ones I got when I went from Cake 1.1 to Cake 1.2. The helpers should be there, you just may have to replace $html-> with $form->. Again, I may be wrong, but give it a try.

  11. ahac says:

    jdm: You are probably using Cake 1.2 (which has new form helpers) while this is written for 1.1.

  12. jdm says:

    Thanks 4 letting me about helpers….

  13. Piotr Kaleta says:

    Hi

    I must say that i’m pretty confused. I treid to work with session&cakephp&redirect and I always ended with erased sesion after redirecting to another controler.

    Although, what do you think about putting some nice ” exit();” after $this->redirect? consider that beacuse when you are redirecting the script is still working

  14. sackjounas says:

    I’m a newbie, in cakephp and this 1.1 a 1.2 cakephp versions issues are driving me crazy.

    I’m trying to do just the same thing but in 1.2 version

    does anyone know, where to find something like this but prepared for cakephp ver. 1.2 ?

    sorry for my bad english

    I think that cakephp 1.2 documentation is poor and don’t know where to find anwers

  15. Osamah says:

    Thank you,
    That was helpfull.

  16. dayg says:

    I’m interested in blocking all access to the application…

    Is there a simpler way of doing that?

    Many thanks in advance.