If you need simple Role based access control without the long RBAC process then this article is just for you. Lets jump to the point.
On your user table make a column named 'roles'. Create the model accordingly. It will be named "User" here.
When you add users you can assign them a role among 'admin', 'user', 'staff' etc etc.
In the file "protected/components/UserIdentity.php" write something like:
class UserIdentity extends CUserIdentity { private $id; public function authenticate() { $record=User::model()->findByAttributes(array('email'=>$this->username)); if($record===null) $this->errorCode=self::ERROR_USERNAME_INVALID; else if($record->password!==md5($this->password)) $this->errorCode=self::ERROR_PASSWORD_INVALID; else { $this->id=$record->id; $this->setState('roles', $record->roles); $this->errorCode=self::ERROR_NONE; } return !$this->errorCode; } public function getId(){ return $this->id; } }
The important line is $this->setState('roles', $record->roles);
It adds user roles to their session.
You can fetch the role of the current user with Yii::app()->user->getState('roles') or simply Yii::app()->user->roles.
Modify or create the "WebUser.php" file under the "protected/components" directory so that it overloads the checkAccess() method.
class WebUser extends CWebUser { /** * Overrides a Yii method that is used for roles in controllers (accessRules). * * @param string $operation Name of the operation required (here, a role). * @param mixed $params (opt) Parameters for this operation, usually the object to access. * @return bool Permission granted? */ public function checkAccess($operation, $params=array()) { if (empty($this->id)) { // Not identified => no rights return false; } $role = $this->getState("roles"); if ($role === 'admin') { return true; // admin role has access to everything } // allow access if the operation request is the current user's role return ($operation === $role); } }
You can define your own logic in this checkAccess() methods.
Make sure this class is used by Yii. The config file "protected/config/main.php" must contain:
'components' => array( // ... 'user' => array( 'class' => 'WebUser', ),
Sidenote:
CWebUser::checkAccess() usually connects to the authorization system loaded in Yii.
Here we are replacing it with a simple system that just deals with roles instead of the hierarchical system defined by the derivatives of CAuthManager. See the official tutorial, Role-Based Access Control for details.
Yii::app()->user->checkAccess('admin') to check if the current user has the 'admin' role.
The call Yii::app()->user->checkAccess('staff') will return true if the user has the role "staff" or "admin".accessRules() using the "roles" attribute of the rule.See examples below.
The controller must contain:
public function filters() { return array( 'accessControl', // perform access control for CRUD operations ); } public function accessRules() { return array( array('allow', 'actions'=>array('admin'), 'roles'=>array('staff', 'devel'), ), array('deny', // deny all users 'users'=>array('*'), ), ); }
Here the "admin" action of the controller has restricted access: only those with roles "staff" or "devel" can access it.
As described in the API doc of CAccessRule, the "roles" attribute will in fact call Yii::app()->user->checkAccess().
You can also use just one menu for all users based upon different roles. for example
$user = Yii::app()->user; // just a convenience to shorten expressions $this->widget('zii.widgets.CMenu',array( 'items'=>array( array('label'=>'Users', 'url'=>array('/manageUser/admin'), 'visible'=>$user->checkAccess('staff')), array('label'=>'Your Ideas', 'url'=>array('/userarea/ideaList'), 'visible'=>$user->checkAccess('normal')), array('label'=>'Login', 'url'=>array('/site/login'), 'visible'=>$user->isGuest), array('label'=>'Logout ('.Yii::app()->user->name.')', 'url'=>array('/site/logout'), 'visible'=>!$user->isGuest) ), ));
A very usual need is to allow a user to update its own data but not other's. In this case, the user's role is meaningless without the context: the data that will be modified.
This is why CWebUser::checkAccess() has an optional "$param" parameter. Now suppose we want to check is a user has the right to update a Post record. We can write:
if (Yii::app()->user->checkAccess('normal', $post)) {
Of course WebUser::checkAccess() must be extended to use this "$params" parameter.
This will depend on your application's logic.
For instance, it could be as simple as granting access iff $post->userId == $this->id.
Total 11 comments
Hi guys
I try to all type of set access role and set role , I got role in controller but this can't be access a action page
thnaks
hari maliya
Hi guys
How to create access role in yii and where in yii application part ?
I want to create access role in yii application but i have a problem and dont know about where to assign role in yii like i have three department role 1.admin -: admin have a all access role in our application 2.staff -: staff same of page and access role like to edit or update 3.user -: user have a all access page only viewing in our application
These type of role can set in controller but i can justify where to write all access in yii and how to set access role ,
thank hari maliya
If you want to assign multiple roles to a user (separated by a comma) you can replace
with
Sorry guys, but this point it's not really clear for me
"The call Yii::app()->user->checkAccess('staff') will return true if the user has the role "staff" or "admin"."
What do i've to specify inside checkAccess? In my app, I've 3 user types (admin, operator, account) and i'd like to filter the access inside controllers and filter displayed content.
Inside the controller, i use
where User::ROLE_ADMIN and User::ROLE_OPERATOR are int 1 and 2, and it's the value assigned inside userIdentity
where $record->role_id can be 1 or 2
But it's not working, if i chanche the accessRules with
users with User::ROLE_OPERATOR can access anyway. :(
Any suggestion? Thank you
ps:
this is the code inside checkAccess
You can also use YiiSmartMenu extension.
Hello,
I needed to be able to check for multiple roles. With a minor change I can now do this:
*Note: you can do any combination | ; , . I just choose commas. The command will find any match.
Place the following below $role === 'admin' in protected/components/WebUser.php
Full protected/components/WebUser.php file:
I had the idea, thanks.
Thank you very much for the text.
If set autoLogin=>true in config all data will saved in cookie and i can change my role. WebUser it's better place for method getRole().
Hi, Thank you for a great text! I've been looking for "as simpliest as possible" solution like that, to incorporate it into smaller projects, that do not need a complex, "heavy" RBAC module. Thank you again.
I have one doubt, since the methods isAdmin, isUser etc of Utils class are not static (public Methods) How can we refer them as Utils::isAdmin in access rules or i Zii widgest?
Leave a comment
Please login to leave your comment.