Our blog application needs to differentiate between the system owner and guest users. Therefore, we need to implement the user authentication feature.
As you may have found that the skeleton application already provides user authentication by checking if the username and password are both demo or admin. In this section, we will modify the corresponding code so that the authentication is done against the User database table.
User authentication is performed in a class implementing the IUserIdentity interface. The skeleton application uses the UserIdentity class for this purpose. The class is stored in the file /wwwroot/blog/protected/components/UserIdentity.php.
Tip: By convention, the name of a class file must be the same as the corresponding class name suffixed with the extension
.php. Following this convention, one can refer to a class using a path alias. For example, we can refer to theUserIdentityclass with the aliasapplication.components.UserIdentity. Many APIs in Yii can recognize path aliases (e.g. Yii::createComponent()), and using path aliases avoids the necessity of embedding absolute file paths in the code. The existence of the latter often causes trouble when we deploy an application.
We modify the UserIdentity class as follows,
class UserIdentity extends CUserIdentity { private $_id; public function authenticate() { $username=strtolower($this->username); $user=User::model()->find('LOWER(username)=?',array($username)); if($user===null) $this->errorCode=self::ERROR_USERNAME_INVALID; else if(!$user->validatePassword($this->password)) $this->errorCode=self::ERROR_PASSWORD_INVALID; else { $this->_id=$user->id; $this->username=$user->username; $this->errorCode=self::ERROR_NONE; } return $this->errorCode==self::ERROR_NONE; } public function getId() { return $this->_id; } }
In the authenticate() method, we use the User class to look for a row in the tbl_user table whose username column
is the same as the given username in a case-insensitive manner. Remember that the User class was created using the gii
tool in the prior section. Because the User class extends from CActiveRecord, we can exploit
the ActiveRecord feature to access the tbl_user table in an OOP fashion.
In order to check if the user has entered a valid password, we invoke the validatePassword method of the User class.
We need to modify the file /wwwroot/blog/protected/models/User.php as follows. Note that instead of storing the plain
password in the database, we store a hash of the password. When validating the user-entered password, we should compare
the hash results, instead. We use the Yii built-in CPasswordHelper to hash the password and to validate it.
class User extends CActiveRecord
{
......
public function validatePassword($password)
{
return CPasswordHelper::verifyPassword($password,$this->password);
}
public function hashPassword($password)
{
return CPasswordHelper::hashPassword($password);
}
}In the UserIdentity class, we also override the getId() method which returns the id value of the user found in the tbl_user table. The parent implementation would return the username, instead. Both the username and id properties will be stored in the user session and may be accessed via Yii::app()->user from anywhere in our code.
Tip: In the
UserIdentityclass, we reference the class CUserIdentity without explicitly including the corresponding class file. This is because CUserIdentity is a core class provided by the Yii framework. Yii will automatically include the class file for any core class when it is referenced for the first time.We also do the same with the
Userclass. This is because theUserclass file is placed under the directory/wwwroot/blog/protected/modelswhich has been added to the PHPinclude_pathaccording to the following lines found in the application configuration:return array( ...... 'import'=>array( 'application.models.*', 'application.components.*', ), ...... );The above configuration says that any class whose class file is located under either
/wwwroot/blog/protected/modelsor/wwwroot/blog/protected/componentswill be automatically included when the class is referenced for the first time.
The UserIdentity class is mainly used by the LoginForm class to authenticate a user based on the username and password input collected from the login page. The following code fragment shows how UserIdentity is used:
$identity=new UserIdentity($username,$password);
$identity->authenticate();
switch($identity->errorCode)
{
case UserIdentity::ERROR_NONE:
Yii::app()->user->login($identity);
break;
......
}Info: People often get confused about identity and the
userapplication component. The former represents a way of performing authentication, while the latter is used to represent the information related with the current user. An application can only have oneusercomponent, but it can have one or several identity classes, depending on what kind of authentication it supports. Once authenticated, an identity instance may pass its state information to theusercomponent so that they are globally accessible viauser.
To test the modified UserIdentity class, we can browse the URL http://www.example.com/blog/index.php and try logging in with the username and password that we store in the tbl_user table. If we use the database provided by the blog demo, we should be able to login with username demo and password demo. Note that this blog system does not provide the user management feature. As a result, a user cannot change his account or create a new one through the Web interface. The user management feature may be considered as a future enhancement to the blog application.
Found a typo or you think this page needs improvement?
Edit it on github !
Signup or Login in order to comment.