Hey Guys see the creation of a secure and powerful ACL (Access control list) it’s one of the most delicate and important pieces for building a sturdy website. I’ll try to make this task easier sharing the code I used in one of my latest projects. This ACL system works with a MYSQL database which grant us total flexibility creating users and roles.
CREATING DATABASE TABLES
The first step is to create the necessary tables in database:
Table roles
For storing the roles or groups. Each role have is own privileges. This roles will be assigned to each user, and the users will inherit the role privileges.
For storing the roles or groups. Each role have is own privileges. This roles will be assigned to each user, and the users will inherit the role privileges.
1
2
3
4
5
| CREATE TABLE `roles` ( `id` tinyint(1) NOT NULL AUTO_INCREMENT, `role` varchar (20) DEFAULT NULL , PRIMARY KEY (`id`) ) ENGINE=InnoDB AUTO_INCREMENT=5 DEFAULT CHARSET=utf8; |
Now we add some roles to the table:Anonymous: For non-registered visitors.
Registered: For registered visitors.
Admin: For super users.
Registered: For registered visitors.
Admin: For super users.
1
2
3
| INSERT INTO roles (id, role) VALUES (1, 'Anonymous' ); INSERT INTO roles (id, role) VALUES (2, 'Registered' ); INSERT INTO roles (id, role) VALUES (3, 'Admin' ); |
Table acl
To store all the controllers/actions. Each row means a different action that can be performed by the application.
To store all the controllers/actions. Each row means a different action that can be performed by the application.
1
2
3
4
5
6
7
8
| CREATE TABLE `acl` ( `id` int (10) NOT NULL AUTO_INCREMENT, `controller` varchar (100) NOT NULL , ` action ` varchar (100) DEFAULT NULL , PRIMARY KEY (`id`), UNIQUE KEY `controller` (`controller`,` action `) ) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8 CHECKSUM=1 DELAY_KEY_WRITE=1 ROW_FORMAT= DYNAMIC ; |
Table acl_to_roles
Establish the relation between the roles and actions. In other words: Which actions can perform each role/group.
Establish the relation between the roles and actions. In other words: Which actions can perform each role/group.
1
2
3
4
5
6
7
8
9
10
11
12
| CREATE TABLE `acl_to_roles` ( `id` int (10) NOT NULL AUTO_INCREMENT, `acl_id` int (10) NOT NULL , `role_id` tinyint(10) NOT NULL , PRIMARY KEY (`id`), KEY `acl_id` (`acl_id`), KEY `role_id` (`role_id`), CONSTRAINT `acl_to_roles_ibfk_1` FOREIGN KEY (`acl_id`) REFERENCES `acl` (`id`) ON DELETE CASCADE , CONSTRAINT `acl_to_roles_ibfk_2` FOREIGN KEY (`role_id`) REFERENCES `roles` (`id`) ON DELETE CASCADE ) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8; |
Table users
It contains the field role_id, which establish the privileges that each user will inherit from the roles, and the general information about the users: login, password, ETC.
It contains the field role_id, which establish the privileges that each user will inherit from the roles, and the general information about the users: login, password, ETC.
1
2
3
4
5
6
7
8
9
10
11
| CREATE TABLE `users` ( `id` int (11) NOT NULL AUTO_INCREMENT, `role_id` tinyint(1) DEFAULT '1' , `login` varchar (50) DEFAULT NULL , ` password ` varchar (32) DEFAULT NULL , `salt` varchar (50) DEFAULT NULL , PRIMARY KEY (`id`), KEY `login_index` (`login`), KEY `password_index` (` password `) ) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8 CHECKSUM=1 DELAY_KEY_WRITE=1 ROW_FORMAT= DYNAMIC ; |
CREATE THE ACL PLUGIN
Now we need to create the ACL plugin. It will be located in the following path within our library folder: “/library/MyProject/Controller/Plugin/Acl.php”
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
| <?php class MyProject_Controller_Plugin_Acl extends Zend_Controller_Plugin_Abstract { public function preDispatch(Zend_Controller_Request_Abstract $request ) { $auth = Zend_Auth::getInstance(); //var_dump($auth->getIdentity()); $authModel = new Application_Model_Auth(); if (! $auth ->hasIdentity()){ //If user doesn't exist it will get the Guest account from "users" table Id=1 $authModel ->authenticate( array ( 'login' => 'Guest' , 'password' => 'shocks' )); } $request = $this ->getRequest(); $aclResource = new Application_Model_AclResource(); //Check if the request is valid and controller an action exists. If not redirects to an error page. if ( ! $aclResource ->resourceValid( $request )){ $request ->setControllerName( 'error' ); $request ->setActionName( 'error' ); return ; } $controller = $request ->getControllerName(); $action = $request ->getActionName(); //Check if the requested resource exists in database. If not it will add it if ( ! $aclResource ->resourceExists( $controller , $action )){ $aclResource ->createResource( $controller , $action ); } //Get role_id $role_id = $auth ->getIdentity()->role_id; $role =Application_Model_Role::getById( $role_id ); $role = $role [0]->role; // setup acl $acl = new Zend_Acl(); // add the role $acl ->addRole( new Zend_Acl_Role( $role )); if ( $role_id ==3){ //If role_id=3 "Admin" don't need to create the resources $acl ->allow( $role ); } else { //Create all the existing resources $resources = $aclResource ->getAllResources(); // Add the existing resources to ACL foreach ( $resources as $resource ){ $acl ->add( new Zend_Acl_Resource( $resource ->getController())); } //Create user AllowedResources $userAllowedResources = $aclResource ->getCurrentRoleAllowedResources( $role_id ); // Add the user permissions to ACL foreach ( $userAllowedResources as $controllerName => $allowedActions ){ $arrayAllowedActions = array (); foreach ( $allowedActions as $allowedAction ){ $arrayAllowedActions []= $allowedAction ; } $acl ->allow( $role , $controllerName , $arrayAllowedActions ); } } //Check if user is allowed to acces the url and redirect if needed if (! $acl ->isAllowed( $role , $controller , $action )){ $request ->setControllerName( 'error' ); $request ->setActionName( 'access-denied' ); return ; } } }
|