Authentication with rdSimpleAuthComponent
This component should make authentication very easy. The component utilizes the startup() callback so you do not need a beforeFilter. All you should need to do is put the component below in /app/controllers/components. Then make your controller or AppController.
AppController
filename: /app/app_controller.php <?php uses('sanitize');//include the sanitize lib class AppController extends Controller { var $components = array('rdSimpleAuth'); //OPTION 1: protect every page except the loginPage var $rdAccess = '*'; //OR //OPTION 2: an array of actions. var $rdAccess = array('admin_index' => array('Admin','Manager'), 'admin_add' => array('Admin','Manager') ); var $Sanitize; function __construct() { parent::__construct(); $this->Sanitize = &new Sanitize; } } ?>
You can override the settings in your AppController by setting var $rdAccess in each individual controller.
Database Setup
CREATE TABLE `users` ( `id` int(10) NOT NULL auto_increment, `username` varchar(250) NOT NULL default '', `password` varchar(32) NOT NULL default '', `role` varchar(50) NOT NULL default 'User', `name` varchar(255) default NULL, `email` varchar(250) NOT NULL default '', `created` datetime NOT NULL default '0000-00-00 00:00:00', `modified` datetime NOT NULL default '0000-00-00 00:00:00', PRIMARY KEY (`id`) );
Login Method
here is the UsersController::login() method as an example of how to set the session.
<?php class UsersController extends AppController { function login() { //RENDER VIEW IF USER IS LOGGED IN if($this->rdSimpleAuth->valid) { $this->redirect('/users/view'); } //RENDER LOGIN FORM AND THEN HANDLE POST if (empty($this->data)) { $this->render('login'); } else { $this->Sanitize->cleanArray($this->data); if ($this->User->validates($this->data)) { $this->data['User']['username'] = $this->Sanitize->paranoid($this->data['User']['username'],array('.','_','-')); $this->data['User']['password'] = md5($this->data['User']['password']); $this->data = $this->User->find(array('User.username'=>$this->data['User']['username'], 'User.password'=>$this->data['User']['password'])); if (is_numeric($this->data['User']['id'])) { //sets up the session vars $this->rdSimpleAuth->set($this->data['User']); /* This was causing problems when 'redirect' was set to something else. * Don't read it from session, instead use the variable from the component. * @author Mandy */ //$this->redirect( $this->Session->read('rdAuth.redirect') ); $this->redirect($this->rdSimpleAuth->loginPage); } else { $this->data['User']['password'] = ''; $this->set('message', 'Invalid login/password'); } } else { $this->data['User']['password'] = ''; $this->set('message', 'Invalid login/password'); $this->validateErrors($this->User); } } } }
Usage
Ok in your controllers you have $this→rdSimpleAuth available. lets say you want to check if the user is a member of the admins array. $this→rdSimpleAuth→admin should equal 1;
in the view you can use $this→controller→rdSimpleAuth→admin
Something a little trickier is to check if someone has the permissions to do some. Lets say we have the roles, Admin, Manager, User, Anon. Our allows array might look like $this→rdSimpleAuth→allows = array(’Admin⇒‘Admin’,’Manager’⇒‘Manager’,’User’⇒‘User’); we can put this in the beforeFilter or just add it directly to the component for each app. we can use the perms() method to check.
if($this->rdAuth->perms('User')) { //every role before User will have permission //so Admin, Manager, and User would all pass }
using the roles to in the add form
in the controller we put $this→set(’roles’, $this→rdSimpleAuth→roles);
now in the view we can use <?php echo $html→selectTag(’User/role’, $roles, $html→tagValue(’User/role’), null, null, false);?>
this is what we might want to give to admin user, but if its someone its a regular registration form we just want to set the role by default. In this case we do: $this→data[’User’][’role’] = end($this→rdAuth→roles);
rdSimpleAuthComponent
filename: /app/controllers/components/rd_simple_auth.php
<?php /* * rdSimpleAuth Component * * @author gwoo <gwoo@rd11.com> * @version 1.1.4.3104 * @license MIT * */ class rdSimpleAuthComponent extends Object { var $components = array('Session'); /** * the redirect if auth fails. * * @var string * @access public */ var $loginPage = '/users/login'; /** * all roles available * * @var array * @access public */ var $roles = array('Admin'=>'Admin'); /** * if role assigned to the logged in user matches admins array * * @var array * @access public */ var $admins = array('Admin'=>'Admin'); /** * allowed roles * * @var array * @access public */ var $allows = array('Admin'=>'Admin'); /** * id of the logged in user * * @var unknown_type * @access private */ var $id = null; /** * username of the logged in user * * @var string * @access private */ var $username = null; /** * role assigned to the logged in user * * @var string * @access private */ var $role = null; /** * if admins passes then set admin var * * @var bool * @access private */ var $admin = null; /** * if role passes users set allowed * * @var boolean * @access private */ var $allow = null; /** * Valid if role, username , and id exist. * * @var string * @access public */ var $valid = false; /** * Error messages to be displayed if the user is short of access for the requested action. * * @var string * @access private */ var $errors = null; /** * Uses callback to automatically check rights * @return redirect if check fails */ function startup(&$controller) { $this->set(); if(!isset($controller->params['url']['url'])) { $controller->params = array('url'=>array('url'=>'')); } $vars = get_class_vars($controller->name.'Controller'); if(empty($vars['rdAccess'])) { $vars = get_class_vars('AppController'); } if(!empty($vars['rdAccess']) && !strstr($controller->params['url']['url'], substr($this->loginPage, 1))) { if($this->check($controller->action, $vars['rdAccess']) == false) { $this->Session->write('rdAuth.redirect', $controller->params['url']['url']); $controller->redirect($this->loginPage); exit; } else { if($this->Session->check('rdAuth.redirect')) { $redirect = $this->Session->read('rdAuth.redirect'); $this->Session->del('rdAuth.redirect'); $controller->redirect($redirect); } } } } /** * Function to check the session and return local vars * * @param string $data used for login method * @return errors */ function set($data='') { if($data) { $this->Session->write('rdAuth.id', $data['id']); $this->Session->write('rdAuth.username', $data['username']); $this->Session->write('rdAuth.role', $data['role']); } if($this->Session->check('rdAuth') && $this->Session->valid('rdAuth')) { $this->id = $this->Session->read('rdAuth.id'); $this->username = $this->Session->read('rdAuth.username'); $this->role = $this->Session->read('rdAuth.role'); if(in_array($this->role,$this->admins)) { $this->admin = 1; } if(in_array($this->role,$this->allows)) { $this->allow = 1; } if($this->id && $this->username && $this->role) { $this->valid = 1; } } elseif($this->Session->error()) { return $this->Session->error(); } } /** * logout method deletes session * * @return errors */ function logout() { $this->Session->del('rdAuth.id'); $this->Session->del('rdAuth.username'); $this->Session->del('rdAuth.role'); $this->Session->del('rdAuth'); if($this->Session->error()) { return $this->Session->error(); } } /** * Function to check the access for the action based on the access list * * @param string $action The action for which we need to check the access * @param array $access Access array for the controller's actions * @return boolean */ function check($action, $access = '') { if($access == '*') { if($this->valid && $this->allow) { return true; } return false; } else if (is_array($access) && array_key_exists($action, $access)) { if($this->role) { if (in_array($this->role, $access[$action])) { return true; } else { return false; } } else if($this->id) { if (in_array($this->id, $access[$action])) { return true; } else { return false; } } else if($this->username) { if (in_array($this->username, $access[$action])) { return true; } else { return false; } } else { return false; } } return true; } /** * Function to check if a access is authorized on a row in the database * your table would have a field that contains the role just like the user table * * @param string $item The field for which we need to check the access * @return boolean */ function perm($item = null) { if (isset($item) && isset($this->role)) { if(in_array($this->role,$this->allows)) { $flipped = array_flip(array_values($this->allows)); if(isset($flipped[$item]) && $flipped[$item] >= $flipped[$this->role]) { return true; } } } return false; } } ?>