I'm familiar with a whole bunch of ways to authenticate users for the web-based administration application we're developing, and even various techniques to keep tabs on authorisation...
However, my question to you is, how would you recommend I implement a fine-grained access control mechanism that offers the following:
- Users belong to 'roles' or 'groups' such as 'salesperson', 'planning', etc.
- The admin menu system shows only 'pages' which have functions relevant to the users role(s)
- Specfic functions within those pages have constraints - for example, on the 'new booking' page, 'salesperson' users can issue a booking 'only in the future', and on the 'edit bookings' page can edit bookings 'one week from now'. However, 'planning' users might be allowed to retrospectively book 'up to one week ago' and edit bookings made by themselves for 'any time period', but bookings made by others only 'up until tomorrow'...
I know I can implement a basic role-based system to satisfy no.1... I have a feeling I should split the entire application into code chunks, each with their own objectID-permissionID relationship so that I can scan the database of permissions to see which objects are available - that would help me with no.2.
Any ideas how I might build the form control for example, which for 'sales' users only displays a date in the future (but displays dates up to 'one week ago' for planning users), then somehow pairing that with a line in the POST parser that checks to see if the date is in fact within the expected range?
I've played around with the idea I should save each code chunk to the database, then have an object table which dynamically builds the code according to the permissions table, so that the only 'file' on the server is the db connection file!
Any ideas welcome... (even if your background isn't php/MySQL)
Some more insight into the problem from a CUSEC presentation by Zed Shaw talking about why "the ACL is dead" - http://vimeo.com/2723800
I developed a library called PHP-Bouncer that I think would meet your needs very well. It currently supports fully managed access which will allow you to use a single call on every page (I recommend using an include of course) and automatically redirect people if they don't have access to a page, as well as automatic retrieval of roles from a database (if you implement the roles in the DB using the included MySQL table setup script). The syntax is pretty simple.
You create the bouncer:
Add your roles (manually):
or from the Database:
Add a user and give them some roles (Note: There is a class called BouncerUser which your User class can extend, it provides all of the role functionality you need!):
Then let the Bouncer manage access to your files:
If you want to show content in a page only if a user has permission to view it, simply wrap it in:
I think for the problem you described this would be a great solution!
If you want to build real fine-grained access control (FGAC), just check my article on this subject for MySQL :
MySQL 5.0 Fine-Grained Access Control (FGAC)
Basically, you don't want your business code be dependent on the FGAC implementation, you don't want to mix FGAC code in
where
clause of theselect
statements of your business rules. This article shows solutions to avoid cluttering of SQL statements.In a bid to implememt a 'native' approach, rather than piggy-backing a framework, I've been playing around with the following. Would anyone rate this approach? Do you foresee any pitfalls?
The above function would query the database and output something like this:
The following code in the page containing the form input:
After the booking has been made, another page allows us to edit that field:
Am I on the rigt track?
Warning, a lot of Zend Framework ahead!
You can easily handle 1. and 2. with Zend_Acl and Zend_Navigation .
For number 3 you will have to query the ACL object in your model and do a lot of stuff by hand. You could utilize Zend Framework for the forms as well and include specific form element validators depending on the users role permission.
EDIT:
If you do not feel like going the ZF route you can at least take a look at how the ACL is handled in ZF.