Yii Framework Forum: An idea for Role Based Access Control - Yii Framework Forum

Jump to content

  • (5 Pages)
  • +
  • 1
  • 2
  • 3
  • Last »
  • You cannot start a new topic
  • This topic is locked

An idea for Role Based Access Control Rate Topic: -----

#1 User is offline   oleksiy 

  • Junior Member
  • Pip
  • Yii
  • Group: Members
  • Posts: 24
  • Joined: 24-February 09

Posted 24 February 2009 - 11:23 AM

Hi all,

I want to listen your opinion about my Role Based Access Control for Yii.
Actually, I love the idea of RBAC in Yii described here http://www.yiiframew...-access-control but I have a question: Why do I have to remember all those role names I've created and why I should verify permissions manually for each piece of code? I'm quite sure that Model should only be modified with correponding Controller Actions. So why not to have permissions and roles closely tied to my controllers and their actions. And let Yii automatically verify user permissions to access  that or other action.

So I've started with a database schema (MySQL):

1)

Posted Image

As you can see each user can have multiple roles. Each role can have multiple permissions. Each permission allows access to corresponding controller/action pair. Also permissions can have business rule associated with it. Business rule is a simple piece of PHP code. For example here is a permission that will allow user to update his own profile (crud generated UsersController class will have a method called loadUser() to load current instance of 'User' model):

return Yii::app()->user->id==Yii::app()->getController()->loadUser()->id;


Here is corresponding SQL: http://paste2.org/p/153292
(i will also attach it to the post)

2) Now we need a filter class that will allow/deny access to the controller/action pair.

Here it is: http://paste2.org/p/153293
(also attached, put it into /protected/filters folder)

3) Now we need to add this filter to controller, this is easy:


// ..... in controller class....
/**
* @return array action filters
*/
public function filters()
{
return array(
  array(
            'application.filters.AccessControlFilter',
          ),
);
}



And that's all! Mostly... I thought it would be good to have an yiic shell command that will be able to create/update/delete/grant/revoke/search permissions, users and roles. I've called it 'rbac', here is its code on PasteBin: http://paste2.org/p/153298

(code also in attachment, put it into /protected/command/shell folder)
and here is a sample console session


>> rbac grant roles=id:1 permissions=id:%
  add permission [1:list users:auth.users/list] to role [1:admins]?      [Yes|No|All|Cancel] a
      added
  add permission [2:delete users:auth.users/delete] to role [1:admins]?      [Yes|No|All|Cancel] Yes
      added
  add permission [3:show my profile:auth.users/show] to role [1:admins]?      [Yes|No|All|Cancel] Yes
      added
  add permission [4:edit my profile:auth.users/update] to role [1:admins]?      [Yes|No|All|Cancel] Yes
      added

>> rbac applist

USAGE
    rbac applist controllers
    rbac applist actions <controller.id>

DESCRIPTION
    This command will list application controllers and their actions.


>> rbac search permissions users=id:1 permissions=action:%show%
+----+-----------------+---------------------+---------------+-----------+---------------------------------------------------------------------------+
| ID | Title          | Description        | Controller.ID | Action.ID | Business rule                                                            |
+----+-----------------+---------------------+---------------+-----------+---------------------------------------------------------------------------+
| 3  | show my profile | show my own profile | auth.users    | show      | return Yii::app()->user->id==Yii::app()->getController()->loadUser()->id; |
+----+-----------------+---------------------+---------------+-----------+---------------------------------------------------------------------------+
RBAC search criteria: permissions=id:3

Search returned 1 rows

>> rbac missing permissions
There are no permissions defined for these actions:
+---------------+-----------+
| Controller.ID | Action.ID |
+---------------+-----------+
| auth.users    | create    |
| auth.users    | admin    |
+---------------+-----------+
Note: we list only those controllers that are using our RBAC filter: application.filters.AccessControlFilter
To find which controllers are not using RBAC filter run >> rbac missing controllers


>> rbac delete permissions=id:%
  delete permission 'list users', id=1    [Yes|No|All|Cancel] n
      skipping
  delete permission 'delete users', id=2    [Yes|No|All|Cancel] n
      skipping
  delete permission 'show my profile', id=3    [Yes|No|All|Cancel] c


>> rbac missing controllers
These controllers are not using RBAC:
+-----------------------------+-------------------------------+
| Controller.ID              | Number of permissions defined |
+-----------------------------+-------------------------------+
| site                        | 0                            |
| auth.roles                  | 0                            |
| auth.globalgroups          | 0                            |
| accounting.employees        | 0                            |
| projectmanagement.customers | 0                            |
+-----------------------------+-------------------------------+


>> rbac create permission auth.roles
Create permission for the auth.roles/update action? [Yes|No|All|Cancel]y
  Enter name: Update role
  Enter description: update any role
  Enter bizrule (leave empty if not needed):
Created permission 'Update role' with id=7
Create permission for the auth.roles/delete action? [Yes|No|All|Cancel]c






Attached File(s)

  • Attached File  rbac.zip (8.16K)
    Number of downloads: 16

0

#2 User is offline   qiang 

  • Yii Project Lead
  • Yii
  • Group: Yii Dev Team
  • Posts: 5,879
  • Joined: 04-October 08
  • Location:DC, USA

Posted 24 February 2009 - 11:58 AM

This looks very nice! I think it is quite useful. You should share it as an extension.

The RBAC implemented in Yii is a generic one that is not tied with MVC. I also believe you can implement the access control you did here on top of the Yii RBAC (e.g. use controller+action as operation IDs)
0

#3 User is offline   oleksiy 

  • Junior Member
  • Pip
  • Yii
  • Group: Members
  • Posts: 24
  • Joined: 24-February 09

Posted 24 February 2009 - 12:12 PM

Thanks! I thought I would add it as extension after:
1) check/add support for other databases, not only mysql
2) add configuration options like db table names, etc
3) it needs testing :)


0

#4 User is offline   oleksiy 

  • Junior Member
  • Pip
  • Yii
  • Group: Members
  • Posts: 24
  • Joined: 24-February 09

Posted 25 February 2009 - 04:34 AM

Added as an extension, hope to hear any suggestions, bug reports, etc :)
http://www.yiiframew.../alternaterbac/
0

#5 User is offline   arsitek 

  • Standard Member
  • PipPip
  • Yii
  • Group: Members
  • Posts: 127
  • Joined: 10-October 08

Posted 25 February 2009 - 08:43 AM

I'm going on build a little CMS with Yii. Where user can update Article like Joomla. Select Section and than select Category to menage their articles.

But I want to ristriction the section access. Any user can update one section but not manage the others.

Can I use RBAC to do this?

Thanks

0

#6 User is offline   oleksiy 

  • Junior Member
  • Pip
  • Yii
  • Group: Members
  • Posts: 24
  • Joined: 24-February 09

Posted 25 February 2009 - 09:20 AM

Hi, surely you can. You will need to create a separate permission named "update my section" and this permission should have a bizrule attached.
The actual PP code in the bizrule will depend on your application, but it may be something like:

return Yii::app()->user->id==Yii::app()->getController()->currentSection()->author_id;

where currentSection() is your custom method of Section Controller which will return model object of currently being processed section.


Quote

I'm going on build a little CMS with Yii. Where user can update Article like Joomla. Select Section and than select Category to menage their articles.



But I want to ristriction the section access. Any user can update one section but not manage the others.



Can I use RBAC to do this?



Thanks

0

#7 User is offline   Anticon 

  • Junior Member
  • Pip
  • Yii
  • Group: Members
  • Posts: 25
  • Joined: 25-February 09
  • Location:Germany

Posted 26 February 2009 - 08:11 AM

Nice Idea.  :)

I found one small error: The PHP-code asks for a table "roles_has_permissions", but the SQL-file contains only the table "permissions_has_roles".
0

#8 User is offline   oleksiy 

  • Junior Member
  • Pip
  • Yii
  • Group: Members
  • Posts: 24
  • Joined: 24-February 09

Posted 26 February 2009 - 08:26 AM

Yep, sorry. It should be called roles_has_permissions.

SQL file updated (attached to the first post).
0

#9 User is offline   Anticon 

  • Junior Member
  • Pip
  • Yii
  • Group: Members
  • Posts: 25
  • Joined: 25-February 09
  • Location:Germany

Posted 27 February 2009 - 03:05 AM

I have tested it with the blog demo. Great work.  :)

I have one suggestion. When I applied it to the PostController I wasn't able to log in. So i added a user named "guest" and added following code to the filter:
class AccessControlFilter extends CFilter {
... 
    protected function getUserid()
    {
        if (Yii::app()->user->isGuest)
        {
        $sql = 'SELECT * FROM users 
                WHERE username="guest"';
        $command = Yii::app()->db->createCommand($sql);
        $row = $command->queryRow();
        $userid=$row[id]; 
        } else {
        $userid = Yii::app()->user->id;
        }
        return $userid;
    }

    protected function preFilter($filterChain)
    {
    ...
        $command->bindParam(":uid", $this->getUserid(), PDO::PARAM_INT);
      //$command->bindParam(":uid", Yii::app()->user->id, PDO::PARAM_INT);"
    ...
    }
...
}


Now I am able to add roles/permissions to a user who is not logged in.

Have you an idea how to show/hide links depending on the rbac? For example the "update"-link should only be visible, if the user has the permission to access it.
0

#10 User is offline   oleksiy 

  • Junior Member
  • Pip
  • Yii
  • Group: Members
  • Posts: 24
  • Joined: 24-February 09

Posted 27 February 2009 - 03:15 AM

Quote

I have one suggestion. When I applied it to the PostController I wasn't able to log in.


Well, if only few actions are needed for guests (like login action) I think it would be better to just bypass AccessControlFilter for this action:


public function filters()
{
  return array(
    array(
            'application.filters.AccessControlFilter - login',
          ),
  );
}


Quote

Now I am able to add roles/permissions to a user who is not logged in.


Yep, I agree, in case you need to allow guests to access more then contact or login action it would be better to follow your solution!

Quote

Have you an idea how to show/hide links depending on the rbac? For example the "update"-link should only be visible, if the user has the permission to access it.


Was going to finish this functionality today :) I will also check it with latest Yii 1.0.3-dev and will then upload new version of RBAC.
0

#11 User is offline   Anticon 

  • Junior Member
  • Pip
  • Yii
  • Group: Members
  • Posts: 25
  • Joined: 25-February 09
  • Location:Germany

Posted 27 February 2009 - 05:50 AM

You're right. To bypass the filter is the easier way. I'm looking forward to test the next version. :)


0

#12 User is offline   oleksiy 

  • Junior Member
  • Pip
  • Yii
  • Group: Members
  • Posts: 24
  • Joined: 24-February 09

Posted 27 February 2009 - 11:36 AM

Okay, new version. :)

Changelog:

* AccessControlFilter renamed to RbacFilter (file and the class, don't forget to update filters() method)
* Added application component Rbac
* requires Yii v1.0.3
* rbac component implements two methods for access validation

Installation:

1. put Rbac.php to /protected/components
2. put RbacFilter.php to /protected/filters
3. put RbacCommand.php to /protected/commands/shell
4. Configure 'rbac' component:


'components'=>array(
        'rbac' => array(
            'class'=>'application.components.Rbac',
        ),
.......


5. add filter to the controllers:

public function filters()
{
  return array(
    array(
            'application.filters.RbacFilter',
          ),
  );
}


6. new methods you can use to check permissions in application code:

Yii::app()->rbac->checkAccess( string $controller, string $action, number $user = null, array $fakeGET = null);


example:

<td><?php
        if(Yii::app()->rbac->checkAccess($this->id, 'update', Yii::app()->user->id, array('id'=>$model->id))){
            echo CHtml::link('Edit', array('update','id'=>$model->id));
        }
        ?></td>


and other method:

public function checkAccessEx(mixed $searchCriteria, number $user = null);


This is more general method but it can't validate business rules.
example:


//true if current user belongs to role 'admins'
$userHasAccess1 = Yii::app()->rbac->checkAccessEx('roles=name:admins');

//true if user belongs to role 'admins' AND has permissions with id=1 OR id=2
$userHasAccess2 = Yii::app()->rbac->checkAccessEx(array('roles=name:admins', 'permissions=id:1,id:2'));


search criteria syntax follows the same as yiic shell rbac command.


new version attached.

Attached File(s)

  • Attached File  rbac.zip (9.42K)
    Number of downloads: 16

0

#13 User is offline   Anticon 

  • Junior Member
  • Pip
  • Yii
  • Group: Members
  • Posts: 25
  • Joined: 25-February 09
  • Location:Germany

Posted 27 February 2009 - 03:44 PM

Works fine for me.

I have attached the blog demo from Yii 1.0.2, where I added the Rbac-extension. There are two user: admin/admin and demo/demo. admin has full rights, demo has only the right to create and update his own posts, but not to delete them.

I hope it is helpful.

Attached File(s)


0

#14 User is offline   Anticon 

  • Junior Member
  • Pip
  • Yii
  • Group: Members
  • Posts: 25
  • Joined: 25-February 09
  • Location:Germany

Posted 01 March 2009 - 01:32 PM

I tried to use Rbac with the blog demo. When I try "rbac missing permissions", I get following error:
Yii Interactive Tool v1.0
Please type 'help' for help. Type 'exit' to quit.
>> rbac missing controllers
These controllers are not using RBAC:
+---------------+-------------------------------+
| Controller.ID | Number of permissions defined |
+---------------+-------------------------------+
| comment      | 0                            |
+---------------+-------------------------------+

>> rbac missing permissions

Fatal error: Call to a member function filters() on a non-object in C:xampphtdocsblog103protectedcommandsshellRbacCommand.php on line 360

C:xampphtdocsblog103>



I added
            $ci = Yii::app()->createController($c['id']);
            if(is_array($ci)) $ci = $ci[0];//added code
            if($ci != null){
                $filters = $ci->filters();

from missing actions. After that, it works. The error appears only with Yii 1.0.3.

Edit:
Attached blog demo from Yii 1.0.3 with Rbac.

Attached File(s)


0

#15 User is offline   FlyBot 

  • Junior Member
  • Pip
  • Yii
  • Group: Members
  • Posts: 64
  • Joined: 20-January 09
  • Location:Ukraine

Posted 01 March 2009 - 03:48 PM

How many queries executed during a check user's permissions? If I want to verify the user and hide when necessary, 10 links with different permissions?
0

#16 User is offline   oleksiy 

  • Junior Member
  • Pip
  • Yii
  • Group: Members
  • Posts: 24
  • Joined: 24-February 09

Posted 02 March 2009 - 04:40 AM

1 SQL query per each checking.

Quote

How many queries executed during a check user's permissions? If I want to verify the user and hide when necessary, 10 links with different permissions?

0

#17 User is offline   Bios Element 

  • Junior Member
  • Pip
  • Yii
  • Group: Members
  • Posts: 63
  • Joined: 13-February 09
  • Location:Ohio, USA

Posted 06 March 2009 - 07:35 PM

I've done some pretty minor edits to switch the tables over to Singular upper case tables. If anyone is interested I'll post the code.
0

#18 User is offline   oleksiy 

  • Junior Member
  • Pip
  • Yii
  • Group: Members
  • Posts: 24
  • Joined: 24-February 09

Posted 07 March 2009 - 03:10 AM

In a week or so I'm going to upload heavily modified code. It will be a configurable Yii module, with own login/logout/signup/passwordForgot features and admin interface for managing roles, permissions and users.
0

#19 User is offline   mocapapa 

  • Advanced Member
  • PipPipPip
  • Yii
  • Group: Members
  • Posts: 428
  • Joined: 04-January 09
  • Location:Tokyo, JAPAN

Posted 07 March 2009 - 06:35 AM

Quote

Edit:

Attached blog demo from Yii 1.0.3 with Rbac.

There may be name mismatch between the table and the code. Error message says

Quote

The table "Post" for active record class "Post" cannot be found in the database.
while the schema shows

Quote

DROP TABLE IF EXISTS `post`;

CREATE TABLE IF NOT EXISTS `post` (

  `id` int(11) NOT NULL auto_increment,

  `title` varchar(128) NOT NULL,

  `content` text NOT NULL,

  `contentDisplay` text,

:

0

#20 User is offline   Bios Element 

  • Junior Member
  • Pip
  • Yii
  • Group: Members
  • Posts: 63
  • Joined: 13-February 09
  • Location:Ohio, USA

Posted 08 March 2009 - 05:49 PM

Quote

In a week or so I'm going to upload heavily modified code. It will be a configurable Yii module, with own login/logout/signup/passwordForgot features and admin interface for managing roles, permissions and users.


Very much looking forward to it.
0

Share this topic:


  • (5 Pages)
  • +
  • 1
  • 2
  • 3
  • Last »
  • You cannot start a new topic
  • This topic is locked

1 User(s) are reading this topic
0 members, 1 guests, 0 anonymous users