Saturday, 25 August 2012

CakePHP Auth Component Implementation


First time I was using Auth component of CakePHP and it took me around 2 complete days to fully understand Auth component and implement it. Documenation is also bit confusing on http://book.cakephp.org/1.3/. I am writing this post for my future reference as well as for those who are having doubts with Auth component. Let's start

1) Very first step is to include Auth component in components array of AppController. As you know for controllers we do most of the common stuff in AppController.

app_controller.php
 
var $components = array('Auth');

2) If you wanna customize Auth component messages and variables use beforeFilter() method for that, as :
     
app_controller.php

function beforeFilter() {
               
                 //it would load User model dynamically. Discussed in detail in step 4
                 $this->Auth->authenticate = ClassRegistry::init('User');
                               
                 //Following is the code to change default variables for username and password
                 //default array is 
                 //var $fields = array('username' => 'username', 'password' => 'password');
                 $this->Auth->fields = array(
                            'username' => 'username',
                            'password' => 'cslab_user_password'
                  );
                  //You can change the default login from /users/login to be any action of your choice.
                  //$this->Auth->loginAction    = array('admin' => false, 'controller' => 'users', 'action' => 'login');
                  //The AuthComponent remembers what controller/action pair you were trying to get to before you were asked to authenticate yourself by storing this value in the Session, under the Auth.redirect key. However, if this session value is not set (if you're coming to the login page from an external link, for example), then the user will be redirected to the URL specified in loginRedirect.
                  $this->Auth->loginRedirect  = array('admin' => false, 'controller' => 'assigned_devices', 'action' => 'index');
                  //You can also specify where you want the user to go after they are logged out, with the default being the login action.
                  $this->Auth->logoutRedirect = array('admin' => false, 'controller' => 'users', 'action' => 'login');
                 //Change the default error message displayed when someone does not successfully log in.                       
                 $this->Auth->loginError     = 'Username/Password Mismatch.';
                //Change the default error message displayed when someone attempts to access an object or action to which they do not have access.                      
                $this->Auth->authError      = 'Please login to view that page.';
 
                 //I have written these three function to check if admin or normal user is logged in and to get username  of the logged in member
                  $this->set('admin',$this->_isAdmin());
                  $this->set('loggedIn',$this->_loggedIn());
                  $this->set('username',$this->_usersUsername());
}

//Checks if user loggedin is an admin
function _isAdmin(){
           $admin = false;
           if($this->Auth->user('role') == ADMIN_ROLE) {
                     $admin = true;
           }
           return $admin;
}
//Checks if user is logged in        
function _loggedIn(){
            $logged_in = false;
            if($this->Auth->user()) {
                         $logged_in = true;
            }
            return $logged_in;
}

//finds username of the loggedin user
function _usersUsername(){
             $users_username = null;
             if($this->Auth->user()){
                       $users_username = $this->Auth->User('username');
             }
             return $users_username;
}

3) Go to your Users controller and write a login() function. 

users_controller.php 
 
function login(){
              //No need to write anything inside function because Auth component handles everything.
}

If you don't wanna customize anything leave it blank otherwise write your code inside. For example  I wanna implement validations on username and password so here is my code : 

function login(){
                  if($this->data){
                             $this->User->set($this->data);
                             if($this->User->validates()){
                                         if ($this->Auth->user()) {
                                                        $this->redirect($this->Auth->redirect());
                                         }
                              }else{
                                          $this->errors = $this->User->validationErrors;
                              }
                    }
                    $this->set('errors',$this->errors);
 }

4) Now write view file :

login.ctp

<?php  echo $session->flash('auth');?> //Display auth messages

<?php  echo $this->Form->create("User"); ?>

<?php echo $this->Form->input("username", array('label' => "Username : ", 'type' => 'text', 'class' => 'tal vat w200p', 'error' => false)); ?><br/>

<?php echo $this->Form->input("pswd", array('label' => "Password : ", 'type' => 'password', 'class' => 'tal vat w200p', 'error' => false)); ?><br/>

<?php echo $this->Html->div("pb10p",$this->Html->link("I forgot my password","/users/forgot",array('class' => 'pl150p')), array('id' => "forgot_password")); ?>

<?php echo $this->Form->end(" Login ",array('class' => 'button')); ?>

Have you noticed i have used "pswd" field name instead of "password" for password field. It's because if we will use "password" field then it would perform automatic hashing even if the field is empty and would skip validation for password as well. I just wanna perform password validation and md5 hashing without salt. So we have to use other name for password field and overwrite hasing. So go to User model and write validation code as well as hashPasswords() function. We also have to set  'authenticate' to the object you're authenticating against (usually this is User, done in step 2) 

user.php
 
var $validate    =   array(
                 'username' => array(
                                'username_should_not_be_empty' => array(
                                                'rule'                      => 'notEmpty',
                                                 'message'            => 'Please Enter Username',
                                                 'last'                       => true
                                 )
                    ),
                    'pswd' => array(
                                    'password_should_not_be_empty' => array(
                                                     'rule'                      => 'notEmpty',
                                                     'message'            => 'Please Enter Password',
                                                      'last'                       => true
                                     )
                     )
);

function hashPasswords($data) {
                if (isset($data['User']['pswd'])) {
                               $data['User']['cslab_user_password'] = md5($data['User']['pswd']);
                                return $data;
                 }
                 return $data;
}


5) To logout from system you have to just write following function :

users_controller.php

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

6) If you wanna another page to get accessed without login, mention it in beforeFilter() function of the controller. For example i also wants to access register and forgot_password functions of users controller  to be accessed publicly then write following code :

users_controller.php

function beforeFilter(){
                parent::beforeFilter();
                $this->Auth->allow('register', 'forgot_password');
 }  

7) You can also your own layout for Authentication error messages like 'authError' and 'loginError' using following line in AppController beforeFilter() function.

message_error.ctp

$this->Auth->flashElement    = "message_error";

this layout file should be saved as ......app\views\elements\message_error.ctp
 
//    Code in /app/views/elements/message_error.ctp
<div class="ui-state-error">
    <?php echo $message; ?>
</div>

8) If you wanna get any information of the loggedin used then you can get it simple as :

$user_email = $this->Auth->user('user_email');

where 'user_email' is users table field.

That's it. If you have any doubt regarding please post your comments below. 


Reference Links : 
 





Thanks!!!!!!!!!! Enjoy Programming :)

No comments:

Post a Comment

Thanks for your valuable comments.

Odoo 10: Close wizard and open standard form

Hi, Today we are going to learn how to open standard form after saving data in wizard. Let's say I have created an wizard to fill bas...