How to create a simple (non-RBAC) authorization system
As I notice reading the forum, this is a frequent doubt, so I decided to write this article.
This article covers only the authorization system. I assume you already know how to create an authentication system ( login ).
Database ¶
Firstly, in the 'user' table, create a new integer field called 'accessLevel', that defines the user's access level
Extending CWebUser ¶
in your config file (usually protected/config/main.php)
'components'=>array(
'user'=>array(
//tell the application to use your WebUser class instead of the default CWebUser
'class'=>'WebUser',
//...
),
),
In your components folder ( protected/components ) create a 'WebUser.php' file and a class like this:
/**
* @property boolean $isAdmin
* @property boolean $isSuperAdmin
* @property User $user
*/
class WebUser extends CWebUser{
/**
* cache for the logged in User active record
* @return User
*/
private $_user;
/**
* is the user a superadmin ?
* @return boolean
*/
function getIsSuperAdmin(){
return ( $this->user && $this->user->accessLevel == User::LEVEL_SUPERADMIN );
}
/**
* is the user an administrator ?
* @return boolean
*/
function getIsAdmin(){
return ( $this->user && $this->user->accessLevel >= User::LEVEL_ADMIN );
}
/**
* get the logged user
* @return User|null the user active record or null if user is guest
*/
function getUser(){
if( $this->isGuest )
return null;
if( $this->_user === null ){
$this->_user = User::model()->findByPk( $this->id );
}
return $this->_user;
}
}
Usage ¶
now to validate the user using the filter accessControl
//in your controller
function accessRules(){
return array(
//only accessable by admins
array('allow',
'expression'=>'$user->isAdmin',
//the 'user' var in an accessRule expression is a reference to Yii::app()->user
),
//deny all other users
array('deny',
'users'=>array('*').
),
);
}
using it in your views
if(Yii::app()->user->isAdmin){
echo 'Welcome, administrator!';
}
if(Yii::app()->user->isSuperAdmin){
echo 'You are the man!';
}
Data representation ¶
Now in your User model, to facilitate the data representation of an integer field do the following
class User extends CActiveRecord{
//define the number of levels that you need
const LEVEL_REGISTERED=0, LEVEL_AUTHOR=1, LEVEL_ADMIN=6, LEVEL_SUPERADMIN=99;
/**
* define the label for each level
* @param int $level the level to get the label or null to return a list of labels
* @return array|string
*/
static function getAccessLevelList( $level = null ){
$levelList=array(
self::LEVEL_REGISTERED => 'Registered',
self::LEVEL_AUTHOR => 'Author',
self::LEVEL_ADMIN => 'Administrator'
);
if( $level === null)
return $levelList;
return $levelList[ $level ];
}
}
//using it in forms
$form->dropDownList($model,'accessLevel',$model->accessLevelList);
//using it in DetailView
$this->widget('zii.widgets.CDetailView',array(
'data'=>$model,
'attributes'=>array(
//...,
array(
'name'=>'accessLevel',
'value'=>$model->accessLevelList[$model->accessLevel],
),
),
));
//using it in GridView
$this->widget('zii.widgets.CGridView',array(
'dataProvider'=>$model->search(),
'columns'=>array(
//...,
array(
'name'=>'accessLevel',
'value'=>'$data->accessLevelList[$data->accessLevel]',
),
),
));
//display the administrator label
echo User::getAccessLevelList( User::LEVEL_ADMIN );
And that is it. I hope that helps you.
Cheers, Gustavo
Read more ¶
- Definitive guide - Authentication and Authorization
- Wiki - Understanding Virtual Attributes and get/set methods
- Wiki - How to add more information to Yii::app()->user
- Wiki - Add information to Yii::app()->user by extending CWebUser
User Contributed Notes 1
Yii already had built in for authorized
Yii had built in function for authorized here
Leave a comment
If you have any questions, please ask in the forum instead.
Join the conversation to share a note.