I have already made the database and the php code needed to implement this customized ACL system. Now I have to 'Authorize' the current user, and that's where I need your advices.
The system is based on a flexible permission assignment both to the system users and system modules. It has also some predefined, let say user-groups, with the ability to make entirely customized groups also. A global rule could also apply on top of the ACL, but it has the lowest priority over groups or users assigned permissions.
To picture it better:
Predefined Groups:
- Limited (No Access)
- Basic User
- Power User
- Administrator
- Visitors (Sample of a customized group)
Here are the access levels (name / value pairs):
- disallow / 0
- allow / 1
- deny / 2
- allow if owner / 3
Note: 'Allow' has the higher priority on 'Disallow', so if you have user X 'Disallowed' on Group A, but 'Allowed' on Group B on a certain access, so he would 'Allowed' finally. On the other hand, if user X has the 'Full Access' by being a member of 'Administrator' Group, but if he just 'Denied' on a certain access, he has not the access at the end, that means 'Deny' has higher priority on 'Allow'.
At the top-level you may have something like these:
- "Administrator" * "1", which means Administrators have full access on the system
- "Visitors" * "0", which means Visitors are not allowed on anything
My question is how to process these kind of checks? Imagine we have a simple authorization mechanism. We would have some indexes in our $_SESSION['user']
like $_SESSION['user']['login'] = true;
and $_SESSION['user']['id'] = $row['user_id']
, right?
Now, if you wanted to implement this mechanism on your script, how you're gonna do it?
I might check for the global access rules at first. Then I would look if the user has already logged-in or not. If yes, just getting all of his groups, and then looking on the permissions' table to see which permissions are assigned to his groups and his user id, and then storing them on the user session. Then when the module says this is my needed permissions to run, I would look then to see if the user has sufficient access to the requested module or not.
Looks pretty complex! Any helps or advice are highly appreciated! :)
Edit:
I'm not using any frameworks. Actually I use, but it's my own. So, there is no pre-made ACL here!
Update:
Do you have any idea about an efficient way to prioritize (overwrite/replace?) ACLs?
Deny
is highest, then Allow
and then Disallow
. Also User
assigned ACLs are highest, then Group
ACLs and finally Global
ACLs.
Here is what I came up with that finally:
There is an Array
, like this:
$_SESSION['ACL'][$module][$action] = $access_level; // 0, 1, 2, 3
First, I would looking for all the Global Rules *
, and will put them on the array:
// The current user can see the map, applied by a global rule
$_SESSION['ACL']['map']['render'] = 1;
// All the other permissions are disallowed by default
$_SESSION['ACL']['*']['*'] = 0;
// He can edit his preferences, (Owner)
$_SESSION['ACL']['user']['*'] = 3;
Then, I will look for Group based ACLs:
// User could access the Analyze module, all the methods
// with Permission Name "report". Applied by being a member
// of "Moderator" Group
$_SESSION['ACL']['analyze']['report'] = 1;
// User NOT allowed to access "groups" module, let say
// it reserved for "admin" group! - To see the ACLs' Overwriting!
$_SESSION['ACL']['groups']['*'] = 0;
After all, I would looking for User assigned ACLs:
// User have Full Access to the "groups" module.
// It's gonna replace the last ACL, applied by "Moderator" group
// Note that the order of processing ACLs is IMPORTANT!
$_SESSION['ACL']['groups']['*'] = 1;
I guess it would works perfectly, any ideas?
It Works Pretty Well Now :)