[ Index ] |
PHP Cross Reference of ACL Module |
[Summary view] [Print] [Text view]
1 Contents: 2 3 1) Preliminaries: What does this extension do? 4 - How does ACL work? 5 - Features of this extension 6 - Limitations of this extension 7 - How does ACL differ from RBAC? 8 - Installation 9 2) How can I use this extension? 10 3) Internals 11 4) Possible Improvements 12 5) Known Bugs** 13 6) Versions 14 15 16 17 18 1) What does this extension do? 19 -------------------------------- 20 21 This extension provides a full-fledged implementation of ACL-based access control. It's ideas are heavily leaned on the way cakePHP implements ACL, but extended both in convenience and power. 22 23 24 - How does ACL work? 25 --------------------- 26 27 In the following I'll only elucidate the really important concepts inherent to ACL - and I'll try to be as brief as possible. For detailed description of how ACL works, delve into specialized texts. 28 29 Every ACL-system consists of at least two types: the ACOs (Access Control Objects) and AROs (Access Request Objects). 30 ACOs are all the objects which are accessed (=> passive behavior), in particular on which specific actions are performed. Their counterpart are the AROs. Those objects take the active part, they try to perform specific actions on the ACOs. 31 32 Each single ARO-node can be linked to several ACOs. All connections between AROs and ACOs also indicate what actions may be performed by the involved ARO-node on the involved ACO-node. In addition to that, both ACOs and AROs may be located in a hierarchy. Therefore they can have parents, inheriting the permissions of the parent node. 33 34 If an action is to be performed, a connection between the ACO and ARO is sought, which has to grant the specified action. If no such connection is found, or if the connection does not grant the desired action, the access is denied. 35 36 37 38 - Features 39 ---------------------- 40 41 - multiple groups for each node (both ACO and ARO) 42 - Unlimited depth in hierarchy 43 - supports also access control filters with backward-compatible syntax 44 - non-recursive permission lookup 45 - convenient, integrated interface 46 - transactions as well as exceptions upon crucial errors 47 48 - Limitations 49 ---------------------- 50 - Due to parametrized static method calls this extension is limited to PHP versions >= 5.3.0. 51 - this extension supports solely positive rights-management 52 => the access check only checks if you are explicitely allowed to do something, it doesn't checkif you are explicitely _denied_ access 53 54 - A fellow told me that INNER JOINs have a different syntax (regarding `` and so on) on different DBMS. The extension was developed with MySQL and was never tested with competitors such as Oracle or PGSQL but it should be an easy task to adjust the things if I knew what to change. 55 56 - The system currently requires numerical primary keys which are all named "id" for both your ACOs and AROs. I keep my eyes peeled but nothing has shown up yet to remedy that in an easy way. 57 58 59 - How does ACL differ from RBAC? 60 ------------------------------- 61 62 As the name already states, Role-based Access Control grants or denies permissions through roles. 63 Access Control Lists uses a more general approach using generalized objects and their relations. In general, ACL is more suited if the access control has to be fine-grained at the object-/document-level. That is, if specific permissions to specific ACOs attached to AROs take precedence over specific permissions to types of ACOs attached to specific users. 64 65 The gist is that the builtin Yii RBAC-system only allows so-called business-rules to check if a given object "belongs" to the given user (or one of his groups). 66 This has several drawbacks: 67 68 1) In order to check the business-rules Yii has to load every (possible suitable) single rule out of the database and execute it (it's plain PHP-code) 69 70 2) Those rules are fixed (PHP-expressions). Therefore one is not able to alter the permissions dynamically without rewriting all the rules. 71 72 3) It's a bad habit to store PHP-Code in the database. 73 74 4) Those rules tend to be broader and thus there is no really convient "fine-grained" control possible. Of course it's possible to achieve the same things possible with ACL using RBAC. Even with a Smart you can reach 70 miles/h. 75 76 77 78 - Installation 79 ------------- 80 81 1) Copy the files in your "modules"-section of your application 82 2) Edit main.php as follows: 83 84 ~~~ 85 [php] 86 'import'=>array( 87 'application.modules.acl.components.*', 88 'application.modules.acl.models.*' 89 ) 90 ~~~ 91 92 93 3) Create the necessary tables using sql.txt 94 4) You are done. 95 96 97 Installation of the Access Control Filter: 98 (It's not possible to introduce a better procedure, as the core development team has rejected to make things protected.) 99 100 First, you have to update the framework itself. Go to framework/web/auth/CAccessControlFilter.php 101 and change line 67 to: 102 103 ~~~ 104 [php] 105 protected $_rules=array(); 106 ~~~ 107 108 In order to use the new Filter, overwrite the method "filterAccessControl" in your controllers: 109 110 ~~~ 111 [php] 112 public function filterAccessControl($filterChain) { 113 $filter = new ExtAccessControlFilter; 114 $filter->setRules($this->accessRules()); 115 $filter->filter($filterChain); 116 } 117 ~~~ 118 119 You are done. There are no changes in syntax or behavior to keep in mind. Roles correspond to User-Groups (and thus Aro-Objects). Everything works just as it did before. 120 121 122 2) How can I use this extension? 123 --------------------------------- 124 125 126 Configuration: 127 128 In order to use this feature, you have add the "RequestingActiveRecordBehavior" to your Model or you can derive your requesting model 129 (usually the User) from "RequestingActiveRecord" instead of "CActiveRecord". 130 (see RestrictedActiveRecord::model) 131 e.g.: 132 133 ~~~ 134 [php] 135 class User extends RequestingActiveRecord{ ... } 136 ~~~ 137 138 139 Secondly, you do the same with the objects to restrict access on - you just use "RestrictedActiveRecordBehavior" as the behavior or "RestrictedActiveRecord" as the base class. 140 141 From now on, whenever you try to to select, update or delete records using the ActiveRecord-objects, access will be automatically checked and you will only get the objects to which the user has access. 142 Feel free to do such stuff: 143 144 ~~~ 145 [php] 146 $img = Image::model()->find(...) // is this my object? 147 $img->key = value; 148 $img->save(); //May I update this object? (notice: an exception is thrown 149 // if rules are violated) 150 151 $images = Image::model()->findAll(...) //You only get the ones you have access to 152 ~~~ 153 154 That's it. You don't believe it? Just try it:-> 155 156 Take a glance at the behaviors: 157 - by default, every user can create a new object of every type 158 - by default, a user has all rights on the objects he himself created 159 160 - if the user is a guest, his rights are equal to the group named "Guest" (see the strategy-configuration to change this) 161 => if you don't create such a group and assign rights, he has no rights 162 => assign all rights for guests to this group and NOWHERE else 163 => you can bypass the Access Check setting RestrictedActiveRecord::byPassCheck to true. 164 => you can "view" the database through the "glasses" of any other ARO than the current user: take a squint at RestrictedActiveRecord::inAttendance 165 166 This may be necessary in certain circumstances, for example if guests can create objects and may update them (employing an authentication mechanism such as cookies) but he himself isn't represented by any dedicated ARO-object (because he is a guest). To anyway allow him to update his own objects, you can bypass the check easily. 167 168 169 170 - Rights Management: 171 --------------------------- 172 173 174 175 ~~~ 176 [php] 177 //Recall: we need the activeRecord, not the identity 178 $user = User::model()->findByPk(Yii::app()->user->id); 179 180 //$activeRecord can be of any type derived vom CActiveRecord 181 $obj = new $activeRecord(); 182 $obj->save(); 183 184 //See later for actions 185 $user->grant($obj, $actions); 186 $user->deny($obj, $actions); 187 $user->may($obj, $action); 188 189 //$group can be any valid alias-string 190 $group = "MyGroup"; 191 192 //checks whether the user is in the given group 193 $user->is($group); 194 195 //note: if strict-mode is disabled, the group will automatically be created upon the first access 196 //otherwise, you have to use the RGroup-Class to create the group 197 $user->join($group); 198 $user->leave($group); 199 200 // Note that it is possible to deny or grant rights multiple times, but it won't 201 // have any effect but letting the performance drop. 202 ~~~ 203 204 205 206 There are three possible syntaxes to denote an object : 207 1) Pass the object directly, e.g.: $user->grant($obj, $actions); 208 2) Use the unique identifier of the object, e.g.: 209 $user->grant(array('model' => 'Image', 'foreign_key' => 'theID'), $actions); 210 3) Use an alias (if the object has an alias): 211 $user->grant("myAlias", $actions); 212 213 Note: You can set the alias only if you access the ARO or ACO using RGroup/CGroup. If you use them only for grouping, you can use the implicit variant, which is probably the most convenient one. 214 215 216 Identification of objects: 217 ------------------------- 218 Every ACL-Object (Aro or Aco) can be dinstinguished using three techniques: 219 220 a) The object itself (it's ID). This ID is automatically created when the object 221 is instantiated. Most times you won't use this direct one. If you bother to do, use RGroup or CGroup. 222 223 b) Using the unique associated: Most ACL-Objects correspond to a real object in your database. You can therefore identify the ACL-Objects by their associated objects: array('model' => 'yourModel', 'foreign_key' => 'aNumericalID'); 224 225 c) Using an Alias. Not all ACL-Objects must directly correspond to real objects. Especially if you perform grouping, you may want to have virtual groups you don't have in your real application. For example "Guest" is such a group: If you don't use it anywhere else, why should you create a corresponding object in your database? 226 You can create such groups using CGroup (ControlGroup => for AccessControlObjects) and RGroup(RequestGroup => for AccessRequestObjects). 227 Note that you can assign aliases to every of your restricted or requesting objects, even if they don't represent a group. 228 229 Example: 230 ~~~ 231 [php] 232 233 $cGroup = new CGroup(); 234 $cGroup->alias = 'MyAlias'; 235 $cGroup->save(); 236 237 $aco = Image::model()->find(...); 238 $aco->join($cGroup); 239 // OR 240 $aco->join('MyAlias'); 241 ~~~ 242 243 244 - Actions: 245 ------------------------- 246 247 Actions are represented by the Model "Action" and reside in {{action}}. 248 The shipped actions are "create", "read", "update", "delete". They should neither be renamed nor removed, as the automatic functionality relies on them. In order to add a possible action, just add a row to your database. 249 This extension supports the wildcard '*', which will automatically be converted into all available actions. 250 Please note that you can limit the actions which can be performed on a specific RestrictedActiveRecord by setting it's possibleActions (it's a static var!). 251 Examples: 252 ~~~ 253 [php] 254 255 $aro->grant($aco, array('read', 'update')); 256 $aro->grant($aco, 'read, update'); 257 $aro->grant($aco, '* - create, delete'); //Corresponds to the preceding example if $aco::possibleActions = array('create', 'read', 'update', 'delete'); 258 ~~~ 259 260 Please keep in mind that "*"" is resolved immediately, so if you add actions later on, you will need to update your objects you granted "*" to. 261 262 263 264 4) Possible Improvements 265 ------------------------- 266 267 - introduce domains 268 Currently, all objects of all models (aco, aro) are stored in the same tables. If you have different types of objects changing more or less often (images change faster than groups or user), it would improve the performance drastically to store both in separate tables. 269 270 - build a full-fledged ACP 271 This has already been done on my behalf, but I recoded the base and the graphical interface is therefore not usable any more. This wish is actually the reason why the extension is shipped as a module. 272 273 274 275 5) Known Bugs 276 -------------- 277 278 Fortunately, this chapter is empty again :-> 279 280 281 6) Versions 282 -------------- 283 284 0.1: 285 286 + proper removal of associated ACL-objects on deletion of the ActiveRecord 287 288 289 + bugfix for errors in conjunction with DataProviders 290 291 292 293 0.2: 294 295 + if strict-mode was disabled, automatic creation of Aro-Collections did not work 296 properly in all cases. This has been fixed. 297 298 + The Access Control Filter has been added 299 300 + some minor changes (most important: CRestrictedActiveRecord) which do not effect exterior 301 302 303 304 0.3 (Current Version): 305 306 + fully recoded 307 308 + added switchable strategies (shipped strategy: Path Materialization) 309 310 + abstracted actions 311 312 + enabled limitation of actions and a new syntax for action-definitions 313 314 + added behaviors 315 316 + introduced several more convenient interfaces 317 318
title
Description
Body
title
Description
Body
title
Description
Body
title
Body
Generated: Sun Jul 1 19:24:45 2012 | Cross-referenced by PHPXref 0.7.1 |