I am just about to undertake building a relatively large PHP system, I just need some ideas on how to implement a certain feature.
I will allow users to register. Once registered, the user will have a security level which will be assigned to their account.
So if I had security levels 1, 2 and 3, what would be the best way to show certain things to people with certain security levels ?
Thank you in advance.
Before you reinvent the wheel, be sure to look whether Zend_ACL is for you. I haven't used it myself but from what it promises in the docs, it can do what you need and much more.
Pekka's comments about looking at the Zend API's are good. Many of the Frameworks for PHP are currently (sadly) badly implemented junk (with hideously amateur code underneath), but the Zend API's are almost uniquely valuable.
If you do roll your own, which there is nothing wrong with doing if you can't find something that fits what you want (and can't be extended easily), then I'd take an OO approach and expose user properties via a class.
e.g.
$user = new User($session->userId);
if (!$user->isAdministrator && !$user->canViewReports)
someErrorHandler("You do not have permission to access this content.");
I'd avoid having fixed levels, but instead follow a roles based approach.
i.e. I'd avoid having levels like:
Staff
Manager
Administrator
And instead I'd go for properties (just as illustrative examples):
read_access
write_access
can_view_logs
can_view_reports
is_administrator
This allows you to be easily more explicit later, when you (inevitably) discover you want an additional permissions group you want have to go back and change existing code.
That doesn't mean putting users in groups is a bad idea (it's not and you could implement this using a groups system, e.g. where by a user could be in both "Reporting" and "Logs"), but assumptions about security levels being hierarchical are typically the wrong approach (e.g. Level 1=Staff, Level 2=Managers, Level 3=Admin) - this is because you almost always end up needing a system that's more flexible than a simple hierarchical system allows.
In practice if you do end up taking this approach, you may want to have a Permissions or Group class, to avoid having an overly large User class (which might end up full of stuff for getting user properties, setting new passwords, etc).
e.g.
$group = new Group($session->userId);
if (!$group->Administrators && !$group->Reporting)
someErrorHandler("You do not have permission to access this content.");
Related
Closed. This question is off-topic. It is not currently accepting answers.
Want to improve this question? Update the question so it's on-topic for Stack Overflow.
Closed 10 years ago.
Improve this question
I am interested in performing advanced access control for users to access resources within software systems. I work in healthcare IT and a younger me has frequently underestimated the complexity of role-based access control in healthcare. But this question should apply to anyone with complex ACL requirements.
For quite some time php gacl has been my go-to library for the purposes of handling the very complex ACL control issues inside Health IT systems. But I am now working more with javascript in general and node specifically. I have searched npm for libraries to do Access Control in a generalizable way.
I would like to have support for defining actions rather than merely users and resources (3-tier instead of 2) and I would like to have user, action and resource groups, and by implication I would like to have ACL inheritance.
The classic examples from the Star Wars themed manual to that library are rules like:
All members of the crew have (visit, configure, and use) access to
the guns, engines, cockpit and lounge, expect for chewie.
All droids have (visit and use) access to the cockpit, but only R2D2 has
configure access to the engines.
Han has all types of access to all
types of resources.
The basic concepts here include the notion that you can make rules that apply to either groups of users(i.e. crew, passengers or droids) or individuals (Han, and Chewie), that you can have different types of access (visit, configure, use) or groups of access (maintence access = configure + repair + use) to different resources (engine and cockpit) which could also be grouped, (battle-stations = cockpit + guns).
This allows for the configuration of extraordinarily complex access control rules, with relatively simple group-based administration.
So far, I have seen nothing like this outside of php-gacl. I have taken a look at the wonderful javascript based ACL projects and all of them advertise simplicity and ease of use rather than comprehensiveness. This is also true of other typical php ACL libraries (i.e. Zend ACL)
Is someone working on an "advanced ACL" project for node? Is there perhaps a much better approach that I should be looking for somewhere?
php-gacl comes with three parts, one is a php-based admin GUI (that is admittedly over-complex), and an API for CRUD on the rules (that could be easily converted to a REST interface I think) and a very small file that provides ACL checking functionality.
Technically, only the last type would need to be fully ported over to node in order for that software model to work?
On a deeper level, I want to understand what approaches have been used successfully to handle this problem. How is this problem typically solved? Bonus points for those who effectively discuss this problem in terms of node/javascript and perhaps even a particular database approach (relational vs non-relational). I understand that there are lots of theoretical underpinnings for doing this right/wrong (i.e. lots of opinion over RBAC, vs ACL). What I want is something theoretically solid, or almost-solid that still "just works" from a library standpoint. I am focused on Javascript, but it would be nice to understand how other languages are practically solving this problem.
If you can avoid using any kind of ACL, you are usually better off. They are complex to administer. You would be better off modeling three levels of security checks:
URL/IP Address/or other accesspoint security check
Method upon resources check. Whatever entities you want to modify or manipulate you put permission checks on that. I.E. Business rules type of access.
Entity Resource check. If a user/API/OAuth token has access AT ALL to an entity
This can be accomplished using an RBAC. The roles for your organization/site each are assigned a set of access/modification/manipulation permissions. Users are assigned a role(s), but the three levels of checks check the PERMISSIONS, not the role.
I would look at Spring Security and RBAC as a google search, and model on that. Here are a few links that I have found useful:
http://www.xaprb.com/blog/2006/08/16/how-to-build-role-based-access-control-in-sql/
http://www.xaprb.com/blog/2006/08/18/role-based-access-control-in-sql-part-2/
(because all the 'primitive' examples and crazily named checks in Spring Security, you will be advised to read articles that offer the use of alternative names and uses for the Spring permission 'hasRole()' checks. The following article discusses this in the design of an RBAC)
http://springinpractice.com/2010/10/27/quick-tip-spring-security-role-based-authorization-and-permissions/
(A good presentation on flexible uses of Spring Security, including RBAC)
http://www.infoq.com/presentations/Spring-Security-3
(The following gives a GOOD description of the RBAC problem and solutions, and is designed for PHP)
http://www.tonymarston.net/php-mysql/role-based-access-control.html
A PHP framework with a RBAC implementation:
http://trac.symfony-project.org/wiki/UserRbac
And finally, the class diagram for Spring Security. You will notice that it allows putting security information in a PARALLEL table to the entities being protected. This is by design, so that Spring Security can be added later, or taken out, or replaced easily. But it also means more tables.
http://code.google.com/p/uclm-esi-alarcos/source/browse/trunk/documentation/memoria-pfc/Figuras/Cap5/spring-security-class-diagram.png?r=295
In the documentation they mention as an example that we can restrict access to a comment.
But if I didn't get it wrong, the system would be storing a different ACE for each instance. So I guess there would be at least one extra row somewhere in the db for each comment.
Is this suitable for high-traffic sites ? Could this create a bottleneck ?
How do sites like stackoverflow or wikipedia manage their ACL's?(I might have to create another post for this question)
PS: Please don't bring the 'premature optimization' thing, I prefer to make this kind of things right by design. Gradual optimization can always be done in other places.
I am building a website with individual user customization in mind. So for instance, client #1 may say i want this feature to be designed for my account and then user #2 may say i want this added to my account. I was thinking of implementing a php if code where upon authentication those features will be loaded each time they login. But i have hundreds of thousands of customizations that i will be doing, to add each php code for each client will be terrible, is there a way i can do it more easily and with less stress?
Added from comments to particular answer:
"Basically i am running the technical side of a business intelligence company. We offer various reports and information along with a dozen analytic tools. So one user might say i want all that you offer plus a custom feature where a particular area of the business is being analyzed and then upload to their account. As you can imagine there can be hundreds of such requests for a lot of accounts."
Your best bet is to either design yourself a framework, or find an existing one that supports this level of customization. Either way, it's not a small job, and launching code for each user leaves you prone to security issues and bugs arising from out-of-date methods as time goes on.
Ask yourself what kind of customizations you're doing, and if they can be abstracted away from the code level by (for example) a templating system.
Designs can fit in certain generic requirements. So until and unless you have some generic requirements, you can not do the design. For example, if requirement is for different look and feel for each client, you might go for dynamic theming. Similarly, for positional changes for different users, you can think of user profiling. For language, also you can keep the user language as part of the profile. Study different approaches for user profile management and then take a step ahead.
As others have said, its impossible to give a specific answer without knowing a lot more about what you mean by "Customization". The only sensible answer is the one you've already provided - i.e. to implement as much as possible of the variable behaviour in data.
This in itself may not be a trivial exercise - on one application I worked on, I designed a heuristic artificial intelligence engine (in PHP) which was hugely successful - but this was a fairly complex exercise in software engineering, and one I'd be hesitant to recommend to anyone who needs to ask the question.
Assuming that pushing all the application logic into data is not practical, then there are some other approaches you might consider, e.g. splitting the customizations into seperate php files (or templates if its just a display thing):
<?php
session_start();
/* do authentication checks...*/
$app=$_SESSION['user_profile'] . '/' . dirname($_SERVER['SCRIPT_NAME'] . '/inc.php');
if (! include_once($app)) {
include_once('default/'.dirname($_SERVER['SCRIPT_NAME'].'/inc.php');
}
...
Although it would be posible to store php code in a database and eval it at runtime - I'd not recommend this as it opens the door to code injection attacks. OTOH, it may prove easier to implement the customizations in a different language and call that from PHP e.g. prolog.
C.
I'm wondering what more experienced developers think about how to handle almost identical processes, such as a user creating a profile and a user editing their profile. At the moment I have a single controller method and single view which handle the distinction between a new user and existing/editing user, just by passing around an $editing flag, so i know to handle any slight differences between the two. Having these conditionals throughout my controller method and view feels a little messy, but then it also feels like a lot of duplication to create a distinct view and controller method for each situation. What do people tend to do in this situation?
I think you should always consider the long-term aspects of design decisions.
It may be cleaner to separate these functions, but then you have two clean functions. So in terms of aesthetics you could argue either way. There is the age old trade-off between clean duplicated code and maintainabilty.
However in the long term other considerations come into play, and you start to think about risks. The risk of duplicating the code is that the two code parts become out of sync, potentially in subtle ways that are hard to detect (e.g. able to add data that is rejected on update). This can be much worse if you are not the person maintaining the code, or you have not touched the code for a long time.
So IMHO keep the editing flag. You have everything in one place, messy though it is.
When I set up a system which can create new users, I tend to require only minimal information on registration - email and password for instance.
Then, the "profile" section of your site can then handle all the editing of the remaining user details, without having to worry about whether or not this is a new or existing user.
In my experience, people tend to get put off when registering for something if too many questions are asked right at the beginning! Delay what is not really necessary, and collect that information later!
I control access to some of my static web resources with some PHP logic. Because directory-based authorization through the webserver is not suitable or easily possible.
A combination of things determines whether access is granted or denied. And these rules change from time to time.
In the beginning it was a simple regex path match, and a check of one session variable. It's more complicated now as there's a few more variables involved.
I'm wondering how to go about refactoring this so it's quick and easy to change the rules. When it was a simple "if this AND this, then deliver, else 403." it was fine to do it in straight PHP. Now the conditions are more complex and there's a couple levels of nesting each with common but slightly different conditions within. This is all easy enough to refactor, but it's not the most intuitive and easy to update.
I'm thinking of one of two things.
Establish classes for each of the top level of conditions and use a Strategy Factory to pick the right one authorize. Derive them all from a base class containing the common bits and overload whatever's necessary. I think this could still be prone to some shuffling around when some conditions change.
Make a simple engine that iterates a 2d array of ordered rules sort of like firewall rules. Something like: <allow|deny>, <auth_group>, <path_regex>, <other vars>
I haven't fully thought this one through but it seems like it would be easier to update and also to read as a human.
What would you do? Is there an established pattern or library I can use for this?
I faced this similar problem in another app some time ago. Where I wanted an easy to update way of chaining rules and outcomes together based on several levels of conditions. This isn't as complicated as that app, but I'd be interested to hear about patterns people use to solve this kind of problem.
You might want to check out Zend_Acl, which is an object-oriented PHP class to manage hierarchies of privileges on hierarchies of resources. You might not be able to use this component as is, but it could give you some insight into how you want to implement your own system.
Zend_Acl is part of the Zend Framework PHP 5 class library, but like many classes in ZF, Zend_Acl can be used independently. There's no need to use the rest of Zend Framework.
You could also use a small logic engine (think prolog) to easily state facts and rules which would allow you to quickly query wether or not access to a resource should be allowed. Logic based rule engines like this are often very efficient and should allow you to very easily model a solution for this kind of problem domain.
I would use the Specification Pattern. It allows you to combine rules. You could even create a class to represent a compound rule that would be run (following the pattern) in the IsSatisfiedBy() method.