How do you resolve permissions inside a web page on a control level in web applications?
I often come across clients that are asking for control-level permissions in web applications. So, one role can “Create” and “Update” and other role can only “Update”. Now, this is not a real security problem, most of web security frameworks use filters and can control different actions in a web application. Since each button triggers different action, you can prevent user from in开发者_C百科voking the action he is not supposed to perform.
The real problem is on the visual level. As long as the wrong button is visible, he will be getting “Unauthorized operation” message. I need to show different subset of controls to different user depending on his permissions. Now, I generally create separate page for separate profile, but this implies a lot of duplication. Are there any web frameworks (no matter the technology) that resolve this issue?
Most frameworks should allow you to query a user's permissions (capabilities, whatever) when rendering, even from templates. Like this:
<*pseudocode* if EditPermission.providedBy(user) >
<button ...EDIT... />
<*pseudocode* end>
I also had the problem and I've solved it by using the Zend Framework. You do not have to use the complete Framework itself, but may rely upon Zend_Acl - the authorization part of the framework.
You basically define your role hierarchy and permitted/denied actions per role as you might already know from other frameworks:
$acl = new Zend_Acl();
// two roles
$acl->addRole(new Zend_Acl_Role('moderator'))
->addRole(new Zend_Acl_Role('member'));
// a Resource is something you can map actions to
$acl->addResource(new Zend_Acl_Resource('database'))
->addResource(new Zend_Acl_Resource('database'), 'update');
// now for the acls itself
$acl->allow('moderator', 'database', 'update')
->deny('member', 'database', 'update');
If you know want to show or hide an action depending on the role, it's as simple as using the isAllowed()
-method in your code:
// show button?
if ($acl->isAllowed($user->role, 'database', 'update')
echo '<input type="button" value="update" />';
else
echo '<input type="button" value="update" disabled="disabled" />';
The manual page provides some better insight on Zend_ACL() and Zend_Auth() - the latter provides the authentication part. If you also want to some more automatism in the generation of menupoints according to roles, check out Zend_Navigation as well.
I think most of the frameworks based on the MVC pattern would allow you to have different views for different roles. Because the code is separated from the View it is easier to reuse that logic in different places and situations. Trying to do this in a web forms style app would lead to much duplication because the code that runs the page is tied to the page more closely.
If you are in a web forms situation, instead of duplicating pages you can have the controls (or actions) in a matrix with user roles showing which controls are available to which roles. When the page loads you hide/show or enable/disable the controls based on what's in the matrix for role the user is in.
I've used a few MVC frameworks in Perl and PHP, and they worked the same: they leave you free to build your views as you like. But none of them recommends to use different views for different roles. As roles are usually groups of permissions, making separate views would prevent any creation or modification of roles. So the frameworks recommend to make one unique view, andcheck the permission in the view just as you would in a controller. It also avoids duplication, though the views are more complex.
A couple of examples in PHP, the web's lingua franca:
Symfony (ACL)
// This should be in the controller $securityContext = $this->get('security.context'); // In the view, before adding an "Update' button if (false === $securityContext->isGranted('EDIT', $stuff)) { // ...
Yii (RBAC)
// in the view if (Yii::app()->user->checkAccess('create')) { echo $form->linkButton(...); } if ( Yii::app()->user->checkAccess('update') || Yii::app()->user->checkAccess('updateOwn', $stuff) ) {
Please note that many components, especially forms, are usually not built directly in HTML. So disabling some elements according to permissions is then easier than it is in templates.
精彩评论