Difference between #2 and #13 of
How to setup RBAC with a php file

Changes

Title unchanged

How to setup RBAC with a php file

Category changed

TutorialHow-tos

Yii version unchanged

Tags changed

Authentication

Content changed

In this cookbook I will attempt to explain how to use the lightweight version of [Role-Based Access Control](http://www.yiiframework.com/doc/guide/topics.auth#role-based-access-control) using a php file. This version does not use database but a php file and is controlled by CPhpAuthManager class. ## Configuring the roles: ## By default when setting up this particular type of rbac Yii will look for any defined roles in a file named auth.php and located in protected/data/auth.php
 
For the
 - for sake of easiness I will  add anwe'll use the example of user rbacRBAC to the blog demo. 
 
>Info: Yii expects to read auth.php and get an array() out of it. So we need to create auth.php and return array(); Yii also needs to write to that file when changing roles so make sure to provide enough permission access to that file needed by the system. Next we dHOWEVER: since Yii rewrites the auth.php file into a form that's far more difficult to edit, it's a good idea to edit a **auth.txt** file, where you can format and comment properly, then copy it to auth.php when you're ready to try it. The first time Yii rewrites auth.php it will be apparent why you want to do this.
 
 
D
eclare some roles in our auth.phptxt file: ```php // protected/data/auth.php
 
 
return array(     'reader' =>
 
  
array (    'type'=>CAuthItem::TYPE_ROLE,     'description'=>'Can only read a post',         'bizRule'=>'',
 
        'data'=>''
 
),     'commentor' =>
 
  
array (     'type'=>CAuthItem::TYPE_ROLE,    'description'=>'Can post a comment',         'bizRule'=>'',
 
        'data'=>''
 
 
),     'admin' =>
 
  
array (    'type'=>CAuthItem::TYPE_ROLE,    'description'=>'Can read a post and post a comment',  'children'=>array(   'reader','commentor',  },),
 
        'bizRule'=>'',
 
        'data'=>''
), ),; ``` The above code declares 3 different types of roles: 1 - **reader** - this type of role can only read a post but not post any comments 2 - **commentor** - this role gives access only to the comments form section to post a comment. 3 - **admin** - which can read a post and post a comment (consists of both roles above). ## Configuring the accessRules(): ##
 
 
Now that we've setup our roles we should move to apply them in action. In this example I will only apply them to our PostController as below:
 
 
 
```php 
public function
The **bizRules** and **data** elements aren't needed by this role scheme, but CPhpAuthManager seems to require them (and it will fail without them).
 
 
Once you've edited the file, put it in place:
 
 
    $ cp auth.txt auth.php
 
    $ chmod a+w auth.php               _# make sure Apache can write to it_
 
 
If you have to make a change to the roles, do it in the .txt file and re-copy to auth.php
 
 
## Configuring the accessRules(): ##
 
 
Now that we've setup our roles we should move to apply them in action. In this example I will only apply them to our PostController as below:
 
 
 
```php 
// in protected/controllers/PostController.php
 
 
class PostController extends CController {
 
 
    public function filters()
 
    {
 
        return array(
 
            'accessControl'           // required to enable
accessRules() );
 
{}
 
    public function accessRules()
 
    {
 
return array(          array('allow', // allow readers only access to the view file         'actions'=>array('view'),         'roles'=>array('reader'),         ),
 
                );
),
 
 
            array('deny',   // deny everybody else
 
                'users' => array('*')
 
            )
);
 
}     ...
 
``` The above code should be pretty clear - allow user with 'reader' role access to the view action. NOTE: Yii accessRules default to **allow**, so the explicit deny is required if you want this behavior.
 
 
## Configuring our tbl_user in our database: ## Next we add an additional field to our tbl_user. We call that field role (varchar 30). We also need two user entries in this table. We already have the 'demo' one from the blog tutorial and add a 'test' one. In the 'demo' role field entery 'reader' as data and for 'test' enter 'admin' as a role.

## Assigning roles: ##
[...]
```php
public function authenticate()
{ $user=User::model()->find('LOWER(username)=?',array(strtolower($this->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;                          $auth=Yii::app()->authManager;                          if(!$auth->isAssigned($user->role,$this->_id))                             {
 
                            if($auth->assign($user->role,$this->_id))
 
                                    {
 
                                Yii::app()->authManager->save();
 
                            }
 
                            
 
                        
{
 
if($auth->assign($user->role,$this->_id))
 
{
 
Yii::app()->authManager->save();
 
}
 
}   $this->errorCode=self::ERROR_NONE; } return $this->errorCode==self::ERROR_NONE; } ```
 
The code we have added to the original UserIdentity class is:  
```php $auth=Yii::app()->authManager; //initializes the authManager                         
 
if(!$auth->isAssigned($user->role,$this->_id)) //checks if the role for this user has already been assigned and if it is NOT than it returns true and continues with assigning it below                             {
 
                            
{
 
if($auth->assign($user->role,$this->_id)) //assigns the role to the user                                     {
 
                                Yii::app()->authManager->save(); //saves the above declaration
 
                            }
 
                            
 
                        
{
 
Yii::app()->authManager->save(); //saves the above declaration
 
}           
 
} ``` >Info: Please see comments at the end of the lines for explanation on what every line of code does. It is important to remember that it is good practice to check if a roles has already been assigned becuase Yii assignes roles and does not delete them until you call the revoke() function. In canse you forget and try to re-assign a role Yii will return an error. Another important point is when you assign a role you must save it by calling Yii::app()->authManager->save();
[...]
```php
'components'=>array(
 
    'authManager'=>array(
 
                     'class'=>'CPhpAuthManager',
 
                ),
 
),
 
```
 
This basically activates the authorization Manager of the application and tells yii that we want to use CPhpAuthManager class to take care of our accessControll. When you login Yii will assign a role to your user id. After you login open up the auth.php file and see that Yii has re-aranged it in the appropriate way.
 
 
For the sake of testing our functionality we should now add some rbac check to our views/post/view.php:
 
 
```php 
<?php if(Yii::app()->user->checkAccess('commentor')): ?>
 
 
<h3>Leave a Comment</h3>
 
            .........//your /commnet/_form here
 
<?php endif; ?>
 
```
 
 
Place the above code around your comments form section in the view file to check if the user has enough access privileges to post a comment.
 
 
You should now have a working privilege based system. One more thing left for our cookbook to be complete. 
 
 
>Info: When the user logs out we need to delete the assigned role otherwise if you change that user's role while he is offline and when he comes back and logs in again he will end up with two roles: the old one and the new one! So we place the below code in our logout action in the SiteController:
 
 
 
 
```php 
public function actionLogout()
 
{
 
                $assigned_roles = Yii::app()->authManager->getRoles(Yii::app()->user->id); //obtains all assigned roles for this user id
 
                if(!empty($assigned_roles)) //checks that there are assigned roles
 
                    {
 
                    $auth=Yii::app()->authManager; //initializes the authManager
 
                    foreach($assigned_roles as $n=>$role)
 
                        {
 
                        if($auth->revoke($n,Yii::app()->user->id)) //remove each assigned role for this user
 
                        Yii::app()->authManager->save(); //again always save the result
 
                    }
 
                    
 
                }
 
                Yii::app()->user->logout(); //logout the user
 
$this->redirect(Yii::app()->homeUrl); //redirect the user
 
}
 
```
 
 
## Adiitional/optional settings: ##
 
 
In your auth.php file you can use the following parameters:
 
- __`type`__ => role,task,operation
 
- __`description`__ => describe the type
 
- __`bizRule`__ => apply business rule
 
- __`data`__ => used in the business rule
 
- __`children`__ => inherit other roles/tasks/operations
 
 
The 'type' is represented by the following constants in the CAuthItem class:
 
 
```php 
const TYPE_OPERATION=0;
 
const TYPE_TASK=1;
 
const TYPE_ROLE=2;
 
```
 
 
## Related readings
 
[Role-Based Access Control](http://www.yiiframework.com/doc/guide/topics.auth#role-based-access-control)<br />
 
[CModel::rules()](/doc/api/CModel#rules-detail)<br />
 
[CAuthManager](http://www.yiiframework.com/doc/api/CAuthManager)<br />
 
[RBAC clarification](http://www.yiiframework.com/forum/index.php?/topic/2313-rbac-confusion)<br />
 
 
>Disclaimer: The above code works for me. I do not guarantee that it will work in all situations. If you need more complex rbac structure use the DB one. I've read all posts in the forum RE rbac
// protected/config/main.php
 
 
return array(
 
    ...
 
    'components'=>array(
 
        'authManager'=>array(
 
            'class'=>'CPhpAuthManager',
 
//          'authFile' => 'path'                  // only if necessary
 
        ),
 
        ...
 
```
 
This basically activates the authorization Manager of the application and tells Yii that we want to use CPhpAuthManager class to take care of our accessControll. When you login Yii will assign a role to your user id. After you login open up the auth.php file and see that Yii has re-arranged it in the appropriate way.
 
 
For the sake of testing our functionality we should now add some RBAC check to our views/post/view.php:
 
 
```php 
<?php if(Yii::app()->user->checkAccess('commentor')): ?>
 
 
<h3>Leave a Comment</h3>
 
            .........//your /commnet/_form here
 
<?php endif; ?>
 
```
 
 
Place the above code around your comments form section in the view file to check if the user has enough access privileges to post a comment.
 
 
You should now have a working privilege based system. One more thing left for our cookbook to be complete. 
 
 
>Info: When the user logs out we need to delete the assigned role otherwise if you change that user's role while he is offline and when he comes back and logs in again he will end up with two roles: the old one and the new one! So we place the below code in our logout action in the SiteController:
 
 
 
```php 
// protected/controllers/SiteController.php
 
 
public function actionLogout()
 
{
 
$assigned_roles = Yii::app()->authManager->getRoles(Yii::app()->user->id); //obtains all assigned roles for this user id
 
if(!empty($assigned_roles)) //checks that there are assigned roles
 
{
 
$auth=Yii::app()->authManager; //initializes the authManager
 
foreach($assigned_roles as $n=>$role)
 
{
 
if($auth->revoke($n,Yii::app()->user->id)) //remove each assigned role for this user
 
Yii::app()->authManager->save(); //again always save the result
 
}
 
}
 
 
Yii::app()->user->logout(); //logout the user
 
$this->redirect(Yii::app()->homeUrl); //redirect the user
 
}
 
```
 
 
## Additional/optional settings: ##
 
 
In your auth.php file you can use the following parameters:
 
- __`type`__ => role,task,operation
 
- __`description`__ => describe the type
 
- __`bizRule`__ => apply business rule
 
- __`data`__ => used in the business rule
 
- __`children`__ => inherit other roles/tasks/operations
 
 
The 'type' is represented by the following constants in the CAuthItem class:
 
 
```php 
const TYPE_OPERATION=0;
 
const TYPE_TASK=1;
 
const TYPE_ROLE=2;
 
```
 
 
## Related readings
 
[Role-Based Access Control](http://www.yiiframework.com/doc/guide/topics.auth#role-based-access-control)<br />
 
[CModel::rules()](/doc/api/CModel#rules-detail)<br />
 
[CAuthManager](http://www.yiiframework.com/doc/api/CAuthManager)<br />
 
[RBAC clarification](http://www.yiiframework.com/forum/index.php?/topic/2313-rbac-confusion)<br />
 
[another related rbac approach](http://yiiframework.ru/doc/cookbook/ru/access.rbac.file)<br />
 
[CPhpAuthManager - how it works, and when to use it](http://www.yiiframework.com/wiki/253/cphpauthmanager-how-it-works-and-when-to-use-it)<br />
 
 
>Disclaimer: The above code works for me. I do not guarantee that it will work in all situations. If you need more complex RBAC structure use the DB one. I've read all posts in the forum re: RBAC
but none of them helped me so the above code has been discovered through trial & error. Use it on your own responsibility.
24 4
21 followers
Viewed: 111 358 times
Version: 1.1
Category: How-tos
Written by: bettor
Last updated by: Stageline
Created on: Feb 7, 2010
Last updated: 11 years ago
Update Article

Revisions

View all history