Fine Access Control

I am familiar with a number of user authentication methods for the web administration application that we are developing, and even various methods to monitor authorization ...

However, my question is for you: 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 only displays “pages” that have functions related to the user role.
  • Certain functions on these pages have limitations - for example, on the “new reservation” page, users of the “seller” can make a reservation “only in the future”, and on the page “Editorial orders” you can edit orders “one” in a week. , users of “planning” may be allowed to retrospectively book “up to one week ago” and edit orders made on their own for “any time period”, but orders made by others only “until tomorrow” ...

I know that I can implement a basic role-based system to satisfy No. 1. I have a feeling that I have to split the entire application into pieces of code, each with its own objectID-permissionID relation, so that I can scan the permissions database to see which objects are available - this would help me without 2.

Any ideas on how I can, for example, create a form control that displays “future” dates for users of “sales” (but displays dates up to “one week ago” for user planning), then somehow combining this with a POST analyzer that checks if the date is really in the expected range?

I played with the idea that I should save every piece of code in the database, and then have an object table that dynamically creates the code according to the permissions table, so the only “file” on the server is the db connection file!

Any ideas are welcome ... (even if your background is not php / MySQL)


More information on the issue from the CUSEC presentation from Zed Shaw talks about why the "ACL is dead" - http://vimeo.com/2723800

+4
source share
4 answers

In an attempt to implement a “native” approach, rather than reinforcing the framework, I played with the following. Anyone appreciate this approach? Do you foresee any pitfalls?

// Check database for existence of this $user against this $object. function get_permission($user, $object){ // Query goes here... if( ... ){ return $permission; } else { return FALSE; } } 

The above function will query the database and output something like this:

 // Result of role-object query. role_ID object_ID permission ------- --------- ---------- salesperson new_booking_date 'min' => 'now', 'max' => '+1 year' planning new_booking_date 'min' => '-1 week', 'max' => '+1 year' salesperson edit_booking_date 'this_user_min' => 'now', 'this_user_max' => '+1 week', 'other_user_min' => 'now', 'other_user_max' => '+1 week' planning edit_booking_date 'this_user_min' => '-1 week', 'this_user_max' => '+1 year', 'other_user_min' => '-1 week', 'other_user_max' => '+1 week' 

The following code on the page containing the form input:

 // Draw form control with javascript date validation... $this_permission = get_permission($this_user, 'new_booking_date'); if($this_permission){ $html->datepicker('min' => $this_permission['min'], 'max' => $this_permission['max']); } 

After the reservation has been made, another page allows us to edit this field:

 // Verify POST data... $this_permission = get_permission($this_user, 'edit_booking_date'); if($this_permission){ if($this_user == $author_user && $_POST['date'] >= strtotime($this_permission['this_user_min'], $date_ref) && $_POST['date'] <= strtotime($this_permission['this_user_max'], $date_ref)){ // Update database... } elseif($_POST['date'] >= strtotime($this_permission['other_user_min'], $date_ref) && $_POST['date'] <= strtotime($this_permission['other_user_max'], $date_ref)){ // Update database... } } 

Am I on the track?

+1
source

Warning, there’s a lot of Zend Framework ahead!

You can easily handle 1. and 2. with Zend_Acl and Zend_Navigation .

For number 3, you will need to query the ACL object in your model and do a lot of things manually. You can also use the Zend Framework for forms and include certain form element validation elements depending on the permission of the user role.

EDIT:

If you don't like going along the ZF route, you can at least take a look at how the ACL is handled in ZF.

+4
source

If you want to create real fine-grained access control (FGAC), just check out my MySQL related article:

MySQL 5.0 Fine-Grained Access Control (FGAC)

Basically, you don’t want your business code to depend on the implementation of FGAC, you don’t want to mix the FGAC code in the where section of the select statements of your business rules. This article introduces solutions to avoid cluttering SQL statements.

+2
source

I developed a library called PHP-Bouncer that I think would fit your needs very well. It currently supports fully managed access, which will allow you to use one call on each page (I recommend using the cursor, of course), and automatically redirect people if they do not have access to the page, as well as automatically search for roles from the database (if you implement roles in the database using the included MySQL script table setting). The syntax is pretty simple.

You create a bouncer:

 $bouncer = new Bouncer(); 

Add your roles (manually):

 // Add a role Name, Array of pages role provides $bouncer->addRole("Public", array("index.php", "about.php", "fail.php")); // Add a role Name, Array of pages role provides $bouncer->addRole("Registered User", array("myaccount.php", "editaccount.php", "viewusers.php")); // Add a role Name, Array of pages role provides List of pages that are overridden by other pages $bouncer->addRole("Admin", array("stats.php", "manageusers.php"), array("viewusers.php" => "manageusers.php")); 

or from the database:

 // conf_* values are set in a config file, or you can pass them in explicitly $bouncer->readRolesFromDatabase(conf_hostname, conf_username, conf_password, conf_schema, "mysql"); 

Add a user and give them some roles (Note. There is a BouncerUser class that can extend your user class, it provides all the necessary functionality of a role!):

 $user->addRole("Logged In"); // This Role doesn't exist in the bouncer, but we can set it anyways if we feel like setting another flag on the user account. This can be useful for displaying content in a page only if a user has a secondary role. $user->addRole("Public"); $user->addRole("Registered User"); 

Then let Bouncer control access to your files:

 $bouncer->manageAccess($user->getRoles(), substr($_SERVER["PHP_SELF"], 1), "fail.php"); // Any time the user tries to go to a page they don't have access to, they will get to // fail.php. Any time they try to go to a page that is overridden for them, they will // get to the overriding page. 

If you want to display content on a page only if the user has permission to view, just wrap it:

 if($user->hasRole("Registered User")){ echo "The content"; } 

I think this would be a great solution for the problem you described!

0
source

All Articles