Join the social network of Tech Nerds, increase skill rank, get work, manage projects...
 
  • Login Form and Authentication Application with Server Side Validation in cakephp

    • 0
    • 0
    • 0
    • 0
    • 0
    • 0
    • 0
    • 0
    • 1.48k
    Comment on it

    A Login Form that uses cakephp auth component to login and logout and access is denied if user is not authorized.

    step 1:  users database table.

    First create users table in your database:

    CREATE TABLE users (
        `id` INT UNSIGNED AUTO_INCREMENT PRIMARY KEY,
        `username` VARCHAR(128),
        `password` VARCHAR(128),
        `email` VARCHAR(128),
        `role` VARCHAR(64),
        `created` DATETIME DEFAULT NULL,
        `modified` DATETIME DEFAULT NULL,
        `status` tinyint(1) NOT NULL DEFAULT '1'
    );

     

    step 2:  Routes.php

    Modify routes.php so that we can have custom link for login , logout and dashboard

    Router::connect('/dashboard', array('controller' => 'users', 'action' => 'index'));
    Router::connect('/login', array('controller' => 'users', 'action' => 'login'));
    Router::connect('/logout', array('controller' => 'users', 'action' => 'logout'));
    
    Router::connect('/', array('controller' => 'users', 'action' => 'login'));

     

    step 3:  User.php

    Next, we will create a file User.php in the app\Model folder. This is our users model where we will write all our validations and logics. I used some of Cakephp inbuilt validation rules as well as my own custom validation rules. My rules are very simple:-Usernames must be unique, non-empty, alphanumeric and be between 5 and 15 characters. Passwords must have a minimum length of 6 and must match the confirmation password. Emails must be unique and be at least 6 characters in length.

    I have created  functions  isUniqueUsername() to find out if a username is unique or not, isUniqueEmail() to find out if an email is unique, alphaNumericDashUnderscore() to only allow alphanumeric values, equaltofield() to check if  password is equal to confirm password. At the end I altered  beforeSave() function so that I can hash the passwords  before saving it into the database. The code is written below.

    App::uses('AuthComponent', 'Controller/Component');
     
    class User extends AppModel {
         
        public $avatarUploadDir = 'img/avatars';
         
        public $validate = array(
            'username' => array(
                'nonEmpty' => array(
                    'rule' => array('notEmpty'),
                    'message' => 'A username is required',
                    'allowEmpty' => false
                ),
                'between' => array(
                    'rule' => array('between', 5, 15),
                    'required' => true,
                    'message' => 'Usernames must be between 5 to 15 characters'
                ),
                 'unique' => array(
                    'rule'    => array('isUniqueUsername'),
                    'message' => 'This username is already in use'
                ),
                'alphaNumericDashUnderscore' => array(
                    'rule'    => array('alphaNumericDashUnderscore'),
                    'message' => 'Username can only be letters, numbers and underscores'
                ),
            ),
            'password' => array(
                'required' => array(
                    'rule' => array('notEmpty'),
                    'message' => 'A password is required'
                ),
                'min_length' => array(
                    'rule' => array('minLength', '6'),  
                    'message' => 'Password must have a mimimum of 6 characters'
                )
            ),
             
            'password_confirm' => array(
                'required' => array(
                    'rule' => array('notEmpty'),
                    'message' => 'Please confirm your password'
                ),
                 'equaltofield' => array(
                    'rule' => array('equaltofield','password'),
                    'message' => 'Both passwords must match.'
                )
            ),
             
            'email' => array(
                'required' => array(
                    'rule' => array('email', true),    
                    'message' => 'Please provide a valid email address.'   
                ),
                 'unique' => array(
                    'rule'    => array('isUniqueEmail'),
                    'message' => 'This email is already in use',
                ),
                'between' => array(
                    'rule' => array('between', 6, 60),
                    'message' => 'Usernames must be between 6 to 60 characters'
                )
            ),
            'role' => array(
                'valid' => array(
                    'rule' => array('inList', array('king', 'queen', 'bishop', 'rook', 'knight', 'pawn')),
                    'message' => 'Please enter a valid role',
                    'allowEmpty' => false
                )
            ),
             
             
            'password_update' => array(
                'min_length' => array(
                    'rule' => array('minLength', '6'),   
                    'message' => 'Password must have a mimimum of 6 characters',
                    'allowEmpty' => true,
                    'required' => false
                )
            ),
            'password_confirm_update' => array(
                 'equaltofield' => array(
                    'rule' => array('equaltofield','password_update'),
                    'message' => 'Both passwords must match.',
                    'required' => false,
                )
            )
     
             
        );
         
            /**
         * Before isUniqueUsername
         * @param array $options
         * @return boolean
         */
        function isUniqueUsername($check) {
     
            $username = $this->find(
                'first',
                array(
                    'fields' => array(
                        'User.id',
                        'User.username'
                    ),
                    'conditions' => array(
                        'User.username' => $check['username']
                    )
                )
            );
     
            if(!empty($username)){
                if($this->data[$this->alias]['id'] == $username['User']['id']){
                    return true;
                }else{
                    return false;
                }
            }else{
                return true;
            }
        }
     
        /**
         * Before isUniqueEmail
         * @param array $options
         * @return boolean
         */
        function isUniqueEmail($check) {
     
            $email = $this->find(
                'first',
                array(
                    'fields' => array(
                        'User.id'
                    ),
                    'conditions' => array(
                        'User.email' => $check['email']
                    )
                )
            );
     
            if(!empty($email)){
                if($this->data[$this->alias]['id'] == $email['User']['id']){
                    return true;
                }else{
                    return false;
                }
            }else{
                return true;
            }
        }
         
        public function alphaNumericDashUnderscore($check) {
            // $data array is passed using the form field name as the key
            // have to extract the value to make the function generic
            $value = array_values($check);
            $value = $value[0];
     
            return preg_match('/^[a-zA-Z0-9_ \-]*$/', $value);
        }
         
        public function equaltofield($check,$otherfield)
        {
            //get name of field
            $fname = '';
            foreach ($check as $key => $value){
                $fname = $key;
                break;
            }
            return $this->data[$this->name][$otherfield] === $this->data[$this->name][$fname];
        }
     
        /**
         * Before Save
         * @param array $options
         * @return boolean
         */
         public function beforeSave($options = array()) {
            // hash our password
            if (isset($this->data[$this->alias]['password'])) {
                $this->data[$this->alias]['password'] = AuthComponent::password($this->data[$this->alias]['password']);
            }
             
            // if we get a new password, hash it
            if (isset($this->data[$this->alias]['password_update']) && !empty($this->data[$this->alias]['password_update'])) {
                $this->data[$this->alias]['password'] = AuthComponent::password($this->data[$this->alias]['password_update']);
            }
         
            // fallback to our parent
            return parent::beforeSave($options);
        }
     
    }

     

    step 4:  AppController.php

    Now add the following lines of code in your AppController:

    public $components = array(
        'DebugKit.Toolbar',
        'Session',
        'Auth' => array(
            'loginRedirect' => array('controller' => 'users', 'action' => 'index'),
            'logoutRedirect' => array('controller' => 'users', 'action' => 'login'),
            'authError' => 'You must be logged in to view this page.',
            'loginError' => 'Invalid Username or Password entered, please try again.'
     
        ));
     
    // only allow the login controllers only
    public function beforeFilter() {
        $this->Auth->allow('login');
    }
     
    public function isAuthorized($user) {
        // Here is where we should verify the role and give access based on role
         
        return true;
    }

     

    step 5:  UsersController.php

    Next, we will create a file UsersController.php in app/Controller. This file contains functions for login, logout, edit, index, add, edit and delete. There is also a function called activate, which is used to activate or deactivate users. I have override the beforeFilter(), so that I can allow login() and add() functions. The  code is written below..

    class UsersController extends AppController {
     
        public $paginate = array(
            'limit' => 25,
            'conditions' => array('status' => '1'),
            'order' => array('User.username' => 'asc' )
        );
         
        public function beforeFilter() {
            parent::beforeFilter();
            $this->Auth->allow('login','add');
        }
    
        public function login() {
             
            //if already logged-in, redirect
            if($this->Session->check('Auth.User')){
                $this->redirect(array('action' => 'index'));      
            }
             
            // if we get the post information, try to authenticate
            if ($this->request->is('post')) {
                if ($this->Auth->login()) {
                    $this->Session->setFlash(__('Welcome, '. $this->Auth->user('username')));
                    $this->redirect($this->Auth->redirectUrl());
                } else {
                    $this->Session->setFlash(__('Invalid username or password'));
                }
            } 
        }
     
        public function logout() {
            $this->redirect($this->Auth->logout());
        }
     
        public function index() {
            $this->paginate = array(
                'limit' => 6,
                'order' => array('User.username' => 'asc' )
            );
            $users = $this->paginate('User');
            $this->set(compact('users'));
        }
     
     
        public function add() {
            if ($this->request->is('post')) {
                     
                $this->User->create();
                if ($this->User->save($this->request->data)) {
                    $this->Session->setFlash(__('The user has been created'));
                    $this->redirect(array('action' => 'index'));
                } else {
                    $this->Session->setFlash(__('The user could not be created. Please, try again.'));
                }   
            }
        }
     
        public function edit($id = null) {
     
                if (!$id) {
                    $this->Session->setFlash('Please provide a user id');
                    $this->redirect(array('action'=>'index'));
                }
     
                $user = $this->User->findById($id);
                if (!$user) {
                    $this->Session->setFlash('Invalid User ID Provided');
                    $this->redirect(array('action'=>'index'));
                }
     
                if ($this->request->is('post') || $this->request->is('put')) {
                    $this->User->id = $id;
                    if ($this->User->save($this->request->data)) {
                        $this->Session->setFlash(__('The user has been updated'));
                        $this->redirect(array('action' => 'edit', $id));
                    }else{
                        $this->Session->setFlash(__('Unable to update your user.'));
                    }
                }
     
                if (!$this->request->data) {
                    $this->request->data = $user;
                }
        }
     
        public function delete($id = null) {
             
            if (!$id) {
                $this->Session->setFlash('Please provide a user id');
                $this->redirect(array('action'=>'index'));
            }
             
            $this->User->id = $id;
            if (!$this->User->exists()) {
                $this->Session->setFlash('Invalid user id provided');
                $this->redirect(array('action'=>'index'));
            }
            if ($this->User->saveField('status', 0)) {
                $this->Session->setFlash(__('User deleted'));
                $this->redirect(array('action' => 'index'));
            }
            $this->Session->setFlash(__('User was not deleted'));
            $this->redirect(array('action' => 'index'));
        }
         
        public function activate($id = null) {
             
            if (!$id) {
                $this->Session->setFlash('Please provide a user id');
                $this->redirect(array('action'=>'index'));
            }
             
            $this->User->id = $id;
            if (!$this->User->exists()) {
                $this->Session->setFlash('Invalid user id provided');
                $this->redirect(array('action'=>'index'));
            }
            if ($this->User->saveField('status', 1)) {
                $this->Session->setFlash(__('User re-activated'));
                $this->redirect(array('action' => 'index'));
            }
            $this->Session->setFlash(__('User was not re-activated'));
            $this->redirect(array('action' => 'index'));
        }


         

    step 6:  login.ctp

    This is the login page that is used to login to the system.

    <div class="users form">
    <?php echo $this->Session->flash('auth'); ?>
    <?php echo $this->Form->create('User'); ?>
        <fieldset>
            <legend><?php echo __('Please enter your username and password'); ?></legend>
            <?php echo $this->Form->input('username');
            echo $this->Form->input('password');
        ?>
        </fieldset>need to
    <?php echo $this->Form->end(__('Login')); ?>
    </div>
    <?php
     echo $this->Html->link( "Add A New User",   array('action'=>'add') );
    ?>


     

    step 7:  add.ctp

    This is the page that allows you to add new users. It is available when you are logged-in. When your are logged out you can not access this page.   

    <!-- app/View/Users/add.ctp -->
    
    
    <div class="users form">
    <?php echo $this->Form->create('User');?>
        <fieldset>
            <legend><?php echo __('Add User'); ?></legend>
            <?php echo $this->Form->input('username');
            echo $this->Form->input('email');
            echo $this->Form->input('password');
            echo $this->Form->input('password_confirm', array('label' => 'Confirm Password *', 'maxLength' => 255, 'title' => 'Confirm password', 'type'=>'password'));
            echo $this->Form->input('role', array(
                'options' => array( 'king' => 'King', 'queen' => 'Queen', 'rook' => 'Rook', 'bishop' => 'Bishop', 'knight' => 'Knight', 'pawn' => 'Pawn')
            ));
             
            echo $this->Form->submit('Add User', array('class' => 'form-submit',  'title' => 'Click here to add the user') );
    ?>
        </fieldset>
    <?php echo $this->Form->end(); ?>
    </div>
    <?php
    if($this->Session->check('Auth.User')){
    echo $this->Html->link( "Return to Dashboard",   array('action'=>'index') );
    echo "<br>";
    echo $this->Html->link( "Logout",   array('action'=>'logout') );
    }else{
    echo $this->Html->link( "Return to Login Screen",   array('action'=>'login') );
    }
    ?>    

     

    step 8:  index.ctp

    index.ctp is the dashboard and you can access the dashboard only when you are logged in.

    <div class="users form">
    <h1>Users</h1>
    <table>
        <thead>
            <tr>
                <th><?php echo $this->Form->checkbox('all', array('name' => 'CheckAll',  'id' => 'CheckAll')); ?></th>
                <th><?php echo $this->Paginator->sort('username', 'Username');?>  </th>
                <th><?php echo $this->Paginator->sort('email', 'E-Mail');?></th>
                <th><?php echo $this->Paginator->sort('created', 'Created');?></th>
                <th><?php echo $this->Paginator->sort('modified','Last Update');?></th>
                <th><?php echo $this->Paginator->sort('role','Role');?></th>
                <th><?php echo $this->Paginator->sort('status','Status');?></th>
                <th>Actions</th>
            </tr>
        </thead>
        <tbody>                       
            <?php $count=0; ?>
            <?php foreach($users as $user): ?>                
            <?php $count ++;?>
            <?php if($count % 2): echo '<tr>'; else: echo '<tr class="zebra">' ?>
            <?php endif; ?>
                <td><?php echo $this->Form->checkbox('User.id.'.$user['User']['id']); ?></td>
                <td><?php echo $this->Html->link( $user['User']['username']  ,   array('action'=>'edit', $user['User']['id']),array('escape' => false) );?></td>
                <td style="text-align: center;"><?php echo $user['User']['email']; ?></td>
                <td style="text-align: center;"><?php echo $this->Time->niceShort($user['User']['created']); ?></td>
                <td style="text-align: center;"><?php echo $this->Time->niceShort($user['User']['modified']); ?></td>
                <td style="text-align: center;"><?php echo $user['User']['role']; ?></td>
                <td style="text-align: center;"><?php echo $user['User']['status']; ?></td>
                <td >
                <?php echo $this->Html->link(    "Edit",   array('action'=>'edit', $user['User']['id']) ); ?> |
                <?php
                    if( $user['User']['status'] != 0){
                        echo $this->Html->link(    "Delete", array('action'=>'delete', $user['User']['id']));}else{
                        echo $this->Html->link(    "Re-Activate", array('action'=>'activate', $user['User']['id']));
                        }
                ?>
                </td>
            </tr>
            <?php endforeach; ?>
            <?php unset($user); ?>
        </tbody>
    </table>
    <?php echo $this->Paginator->prev('<< ' . __('previous', true), array(), null, array('class'=>'disabled'));?>
    <?php echo $this->Paginator->numbers(array(   'class' => 'numbers'     ));?>
    <?php echo $this->Paginator->next(__('next', true) . ' >>', array(), null, array('class' => 'disabled'));?>
    </div>                
    <?php echo $this->Html->link( "Add A New User.",   array('action'=>'add'),array('escape' => false) ); ?>
    <br/>
    <?php
    echo $this->Html->link( "Logout",   array('action'=>'logout') );
    ?>

     

    step 9:  Edit.ctp

    Edit allows you to change user details, you can change all other details except username. The code is written below.

    <!-- app/View/Users/add.ctp -->
    <div class="users form">
    <?php echo $this->Form->create('User'); ?>
        <fieldset>
            <legend><?php echo __('Edit User'); ?></legend>
            <?php
            echo $this->Form->hidden('id', array('value' => $this->data['User']['id']));
            echo $this->Form->input('username', array( 'readonly' => 'readonly', 'label' => 'Usernames cannot be changed!'));
            echo $this->Form->input('email');
            echo $this->Form->input('password_update', array( 'label' => 'New Password (leave empty if you do not want to change)', 'maxLength' => 255, 'type'=>'password','required' => 0));
            echo $this->Form->input('password_confirm_update', array('label' => 'Confirm New Password *', 'maxLength' => 255, 'title' => 'Confirm New password', 'type'=>'password','required' => 0));
             
     
            echo $this->Form->input('role', array(
                'options' => array( 'king' => 'King', 'queen' => 'Queen', 'rook' => 'Rook', 'bishop' => 'Bishop', 'knight' => 'Knight', 'pawn' => 'Pawn')
            ));
            echo $this->Form->submit('Edit User', array('class' => 'form-submit',  'title' => 'Click here to add the user') );
    ?>
        </fieldset>
    <?php echo $this->Form->end(); ?>
    </div>
    <?php
    echo $this->Html->link( "Return to Dashboard",   array('action'=>'index') );
    ?>
    <br/>
    <?php
    echo $this->Html->link( "Logout",   array('action'=>'logout') );
    ?>

 0 Comment(s)

Sign In
                           OR                           
                           OR                           
Register

Sign up using

                           OR                           
Forgot Password
Fill out the form below and instructions to reset your password will be emailed to you:
Reset Password
Fill out the form below and reset your password: