Change the Default Authentication from Text to Database in Yii


If you follow the instruction in Create a Web Application with yiic in TurnKey Linux to generate a web application, the default authentication is text-based. Let’s change to database-based.

Before continue reading, please follow Play Yii Framework with TurnKey Linux to create database table tbl_user and model User which we are going to use for authentication later. If you want to learn more about how authentication works in a generated web application, How Login is handled in Yii Framework will help.

Class: UserIdentity

UserIdentity is a class declared in /protected/components/UserIdentity.php.

The public method authentication() of class UserIdentity contains code to compare username and password. We need to modify them from comparing strings in array to records in table tbl_user.

From Submit to Authenticate

After submitting form data, public method actionLogin() of class SiteController will create an instance of class LoginForm and use its public method login() to check username and password and returned result.

Source code of public method actionLogin() in class SiteController:

public function actionLogin()
{
    $model=new LoginForm;

    // if it is ajax validation request
    if(isset($_POST['ajax']) && $_POST['ajax']==='login-form')
    {
        echo CActiveForm::validate($model);
        Yii::app()->end();
    }

    // collect user input data
    if(isset($_POST['LoginForm']))
    {
        $model->attributes=$_POST['LoginForm'];
        // validate user input and redirect to the previous page if valid
        if($model->validate() && $model->login())
            $this->redirect(Yii::app()->user->returnUrl);
    }
    // display the login form
    $this->render('login',array('model'=>$model));
}

login() doesn’t contain code for authentication. Instead, it creates an instance of class UserIdentity and use its public method authenticate() to compare.

Source code of public method login() in class LoginForm:

public function login()
{
    if($this->_identity===null)
    {
        $this->_identity=new UserIdentity($this->username,$this->password);
        $this->_identity->authenticate();
    }
    if($this->_identity->errorCode===UserIdentity::ERROR_NONE)
    {
        $duration=$this->rememberMe ? 3600*24*30 : 0; // 30 days
        Yii::app()->user->login($this->_identity,$duration);
        return true;
    }
    else
        return false;
}

Class UserIdentity is inherited from CUserIdentity. The public method authenticate() of class UserIdentity contains an array for username and password. If you want to add more users, add them to this array.

Partial source code of class UserIdentity:

class UserIdentity extends CUserIdentity

Source code of public method authenticate() in class UserIdentity:

public function authenticate()
{
    // Old text-based username and password
    $users=array(
        // username => password
        'demo'=>'demo',
        'admin'=>'turnkey',
    );

    if(!isset($users[$this->username]))
        $this->errorCode=self::ERROR_USERNAME_INVALID;
    elseif($users[$this->password]!==$this->password)
        $this->errorCode=self::ERROR_PASSWORD_INVALID;
    else
        $this->errorCode=self::ERROR_NONE;
    return !$this->errorCode;
}

Use Database to Replace Array

To use table tbl_user replacing array, we need to remove this array, add search password by username, and modify access to these value.

Line 13 use scope resolution operator to access parent public method model() in class CActiveRecord from class User to get an active record model instance. Then use this instance to call public method findByAttributes() to search in tbl_user by the given array which contains table field name and matched string.

In line 16 and 19, we need to modify code from accessing array to public property of an instance. Use isset() to check if the given username has matched. If you use is_null() to verify, you will get error “Trying to get property of non-object” when fail to match given username in tbl_user because Null is returned when findByAttributes() found nothing.

Modified source code of public method authenticate() in class UserIdentity:

public function authenticate()
{
    // Remove old text-based username and password
    /*
    $users=array(
        // username => password
        'demo'=>'demo',
        'admin'=>'turnkey',
    );
    */
       
    // Create an instance from model User and search
    $users = User::model()->findByAttributes(array('username'=>$this->username));

    //Swap original if(!isset($users[$this->username]))
    if(!isset($users->username))
        $this->errorCode=self::ERROR_USERNAME_INVALID;
    //Swap original elseif($users[$this->password]!==$this->password)
    elseif($users->password!=$this->password)
        $this->errorCode=self::ERROR_PASSWORD_INVALID;
    else
        $this->errorCode=self::ERROR_NONE;
    return !$this->errorCode;
}

Partial source code of class User:

class User extends CActiveRecord

Thoughts

This is just simply replacing array with database. You may also encrypt password, display different message according to errorCode defined in CBaseUserIdentity, and etc. I will explain them in other post.

Reference

  1. Create a Web Application with yiic in TurnKey Linux
  2. How Login is handled in Yii Framework
  3. PHP: Documentation: isset
  4. PHP: Documentation: is_null
  5. Play Yii Framework with TurnKey Linux
  6. Yii Framework: Documentation: CUserIdentity
  7. Yii Framework: Documentation: CActiveRecord
  8. Yii Framework: Documentation: CActiveRecord: findByAttributes()
  9. Yii Framework: Documentation: CActiveRecord: model()
  10. Yii Framework: Documentation: CBaseUserIdentity
  11. Yii Framework: Documentation: CBaseUserIdentity: errorCode
  12. Yii Framework: Forum: Yii Autentication With Mysql
Advertisements

2 thoughts on “Change the Default Authentication from Text to Database in Yii

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s