RBAC caching

I have started to use rbac implementing operations, tasks and roles.

For each controller-action pair I have an operation (i.e. user_create, user_delete, user_show, user_update).

To only show the buttons and menus people are allowed to use quite a lot of access checking is performed on every request. This results in up to 50 SQL queries per request, which I think is not acceptable.

My solution to this problem is to cache the access rights in the session:

Yii already provides access rights caching within the same request through the CWebUser method ‘checkAccess()’

So I wrote my own user class MyCWebUser extending CWebUser, it only overrides checkAccess().



class MyCWebUser extends CWebUser {

    public function checkAccess($operation,$params=array(),$allowCaching=true) {

        if($allowCaching && !$this->getIsGuest() && isset(Yii::app()->session['access'][$operation])) {

            return Yii::app()->session['access'][$operation];


        $checkAccess = Yii::app()->getAuthManager()->checkAccess($operation,$this->getId(),$params);

        if($allowCaching && !$this->getIsGuest()) {

            $access = isset(Yii::app()->session['access']) ? Yii::app()->session['access'] : array();

            $access[$operation] = $checkAccess;

            Yii::app()->session['access'] = $access;


        return $checkAccess;



In your config file you also need to set the new user class:








When using accessControl filters in the controller the access rights are now cached in the session. Manually checking for access rights also works just like before: Yii::app()->user->checkAccess(‘operation_name’).

There is one disadvantage though: changes to the operations/tasks/roles structure or assignment of roles do not take effect until the user has logged out and then logged in again. In my project I can live with that.

To solve that problem as well access rights could be stored in the file cache for example using a key that contains the userId. When changing role assignment to a user you would then have to delete the cache entry for that user, when changing the operations/tasks/roles structure you would have to delete the cache entries for all users.

I hope these ideas can help somebody, good luck with rbac!

This is very useful. Thanks. :)

I have also the same issue with the rbac and high sql query count thanks for your solution to settle down the problem a bit.

I made ​​some improvements to reduce the problem with the change of permission during the session.

I added a control that forces the revision of permission every 30 minutes.

And I also added the cache control by request of the original class.

class TWebUser extends RWebUser


	private $_access=array();


        public function checkAccess($operation,$params=array(),$allowCaching=true)



                        return true;                


		if($allowCaching && $params===array() && isset($this->_access[$operation]))

			return $this->_access[$operation];                


                $cache = Yii::app()->session['checkAccess'];

                if($allowCaching && !$this->getIsGuest() 

                    && isset($cache[$operation])

                    && time() - $cache[$operation]['t'] < 1800)


                    $checkAccess = $cache[$operation]['p'];




                    $checkAccess = Yii::app()->getAuthManager()->checkAccess($operation,$this->getId(),$params);


                    if($allowCaching && !$this->getIsGuest())


                        $access = isset($cache) ? $cache : array();

                        $access[$operation] = array('p'=>$checkAccess, 't'=>time());

                        Yii::app()->session['checkAccess'] = $access;




                return $this->_access[$operation] = $checkAccess;



I use Rights and my class extends the class of the extension.

It’s important to know that above solution doesn’t work when using bizrules (ex. checking content author by $_GET[‘id’])