You are viewing revision #7 of this wiki article.
This version may not be up to date with the latest version.
You may want to view the differences to the latest version or see the changes made in this revision.
Introduction ¶
I would like to provide you a quick tip on how to implement user level access to your Yii applications.
Please note that this article is a simple example and good security should be taken into account when we play with authentication systems.
Step 1. Setting up ¶
a. Include a field on your user’s table named, yep you guessed, level
b. Create an object ‘LevelLookUp’ that will tell us who is who on this system
class LevelLookUp{
const MEMBER = 0;
const ADMIN = 2;
// For CGridView, CListView Purposes
public static function getLabel( $level ){
if($level == self::MEMBER)
return 'Member';
if($level == self::ADMIN)
return 'Administrator';
return false;
}
// for dropdown lists purposes
public static function getLevelList(){
return array(
self::MEMBER=>'Member',
self::ADMIN=>'Administrator');
}
}
c. Now, lets modify UserIdentity, located on your protected/components (normally by default), so we can store the user Model id on successful authentication, as CWebUser’s id property is set to the user Model’s username by default.
class UserIdentity extends CUserIdentity
{
private $_id;
/**
* Authenticates a user.
* @return boolean whether authentication succeeds.
*/
public function authenticate()
{
$username = strtolower($this->username);
// from database... change to suite your authentication criteria
// -- Nope, I wont include mine --
$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{
// successful login
$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;
}
}
d. Now we need to create our own extended CWebUser and we are going to call it EWebUser for the sake of this example, and save it on protected/components to be loaded automatically by our default’s configuration file.
class EWebUser extends CWebUser{
protected $_model;
function isAdmin(){
$user = $this->loadUser();
if ($user)
return $user->level==LevelLookUp::ADMIN;
return false;
}
// Load user model.
protected function loadUser()
{
if ( $this->_model === null ) {
$this->_model = User::model()->findByPk( $this->id );
}
return $this->_model;
}
}
e. Finally, we modify main.php config file (this file is in protected/config folder) to tell Yii that we want to use our extended version of CWebUser.
// go to the 'user' section
// application components
'components'=>array(
'user'=>array(
// There you go, use our 'extended' version
'class'=>'application.components.EWebUser',
// enable cookie-based authentication
'allowAutoLogin'=>true,
),
Step 2: Putting everything together ¶
Now that we know, who logged, we could easily find out if it is just a member or an administrator and render the elements by checking the level as simple as this:
// for normal content
if(Yii::app()->user->isAdmin())
echo 'Is administrator';
// for CMenus
$this->widget('zii.widgets.CMenu',array(
array('label'=>'Categories',
'url'=>array('/category/index'),
'visible'=>(Yii::app()->user->isAdmin()),
//... More stuff
//...
// for data chuncks
<?php if(Yii::app()->user->isAdmin():?>
<b>My HTML</b>
<?php endif;?>
// for access rules
return array(
array('allow',
'actions'=>array('create','delete','update'),
'expression'=>'$user->isAdmin()'
),
// ...
You can create more methods, like for example, isMember(), or whatever best suits you, in order to display the appropriate view or specific data according to the user level.
Thank you
Thank you for your article. But I think you have error in this line of EWebUser class:
if ( $id !== null )
And why do you use setState/getState? I think that CWebUser stores id itself using this methods.
@derelic
Thanks for pointing me the little bug! I forgot to remove that.
About using setState and getState I used to keep the model's id instead of the username as it internally does, and didn't want to modify CWebUser defaults, that's why I used another variable name (__uid)
Thanks again!
User's ID
You have override CUserIdentity class and now it's getter getId() returns user's ID, not username. That's why in EWebUser class getter getId() will return user's ID too.
@derelict
Thank you again derelict... Code modified...
nice article
Really easy !
thanks!
simple n effective.. short n fast way to get a access system up
Thank you
Thank you for these explanations.
It works perfectly, i just don't understand the way to use LevelLookUp in gridview and listview of user's grids. Could you explain more?
Read only problem
I am trying to implement this nice little access system as well but I am getting a Property "UserIdentity.id" is read only error. Any suggestions?
problem when implement with module based login to module.
Please take a look.why this problem occur with module based login.
http://www.yiiframework.com/forum/index.php/topic/37991-module-based-login-and-user-level-acces-system
b. Create an object ‘LevelLookUp’ that will tell us who is who on this system
Where i will use create this object
b. Create an object ‘LevelLookUp’ that will tell us who is who on this system
Kashif
Simple&Clear Thx
This tutorial helped me alot thx.
To Kashif Nadeem
cerate a php file LevelLookUp.php inside protected/component/
Step 2, Where?
Hi! Thanks for this. I'm new with Yii and I would like to try this but I don't know which file I have to modify in step 2. Do I have to add that code in the main.php file in layouts?
Thanks in advance!
If you have any questions, please ask in the forum instead.
Signup or Login in order to comment.