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
- Create a Web Application with yiic in TurnKey Linux
- How Login is handled in Yii Framework
- PHP: Documentation: isset
- PHP: Documentation: is_null
- Play Yii Framework with TurnKey Linux
- Yii Framework: Documentation: CUserIdentity
- Yii Framework: Documentation: CActiveRecord
- Yii Framework: Documentation: CActiveRecord: findByAttributes()
- Yii Framework: Documentation: CActiveRecord: model()
- Yii Framework: Documentation: CBaseUserIdentity
- Yii Framework: Documentation: CBaseUserIdentity: errorCode
- Yii Framework: Forum: Yii Autentication With Mysql
Thank you so so so much!!!! 🙂
LikeLiked by 1 person
Dear nikolina,
Thank you for your feedback! I am glad to know it helps! 🙂
Have a nice day!
Best regards,
Amigo
LikeLike