-
Notifications
You must be signed in to change notification settings - Fork 0
Tutorial.Authentication Management II.zh_cn
- 在member模块里应用权限控制
前面我们已经介绍了权限操作时的配置文件定义,这一节将结合member模块具体介绍下如何在模块里应用权限控制。我们将主要以member模块后台为例,将后台的controller以及页面的按钮定义成资源,并配置其访问权限,若不允许访问则将资源隐藏,同时在用户用url访问时,跳转到denied页面。
3.1 创建角色
我们要为member模块创建几个角色后台角色。这些角色我们希望都是给member模块用的,所以需要首先创建一个所有member角色的父角色——member-admin,这个父类继承自系统的staff角色,即只有最低的权限,其他的角色都继承自member-admin角色,这样如果我们希望所有角色只能操作member模块,只需要开启member-admin对member模块的allow选项即可。这个角色群拥有的共同权限也都可以直接赋给member-admin。在config目录下创建acl.php并添加如下代码:
路径:usr/module/member/config/acl.php
Code 8.3.1
<?php
return array(
'roles' => array(
'member-admin' => array(
'title' => __('Member Admin'),
'section' => 'admin',
'parents' => array('staff'),
),
'normal-member' => array(
'title' => __('Normal Member Admin'),
'section' => 'admin',
'parents' => array('member-admin'),
),
'temporary-member' => array(
'title' => __('Temporary Member Admin'),
'section' => 'admin',
'parents' => array('member-admin'),
),
),
);
上述的代码就按需求定义了一个模块父角色member-admin,同时定义两个子角色normal-member和temporary-member继承自member-admin。待其他文件都完成后,重新安装就可以在后台看到创建的角色,及其继承关系:
图8-3 后台角色关系界面
3.2 创建资源及权限
接下来我们需要定义后台的资源,这里主要要定义三个资源,其中一个是字符串资源,用来表示用户是否有权限看到筛选条件里的性别一项;另外两个为页面资源,用来判定用户是否有权限访问List Member页面和删除按钮。
- 配置资源和权限
首先我们需要在acl.php文件里配置资源和权限:
路径:usr/module/member/config/acl.php
Code 8.3.2
<?php
return array(
...
'resources' => array(
// Case 2
'admin' => array(
'list-member' => array(
'module' => 'member',
'title' => __('List Member Management'),
'access' => array(
'member-admin' => 1,
),
),
'search-by-gender' => array(
'module' => 'member',
'title' => __('Search Gender Management'),
'access' => array(
'normal-member' => 1,
),
),
'delete-member' => array(
'module' => 'member',
'title' => __('Delete Member Management'),
),
),
),
);
配置权限时,我希望所有member模块的角色都可以看到后台List Member页,因此将父角色member-admin对list-member资源的权限设为1。另外禁止temporary-member看到筛选条件的性别一项,禁止normal-member和temporary-member删除用户。
- 关联页面资源
由于list-member和delete-member资源分别对应listAction和deleteAction,因此要将其关联相应的Controller/Action。在config目录下创建page.php并添加如下代码:
路径:usr/module/member/config/page.php
Code 8.3.3
<?php
return array(
'admin' => array(
array(
'controller' => 'account',
'action' => 'list',
'permission' => array(
'parent' => 'list-member',
),
),
array(
'controller' => 'account',
'action' => 'delete',
'permission' => array(
'parent' => 'delete-member',
),
),
),
);
在代码里我们分别将AccountController的listAction和deleteAction作为list-member和delete-member两个资源的子资源。由于在后台没有用到AJAX调用,所以这里不需要添加exception字段。
**注意:**在实际开发中,不需要将每个action设置成一个资源,只需要将controller设置成资源即可,这里只是为了演示系统对action的权限判定。若想进行action的权限判定,需要在action里再作权限判定。
- 隐藏/显示导航项
虽然现在定义了两个角色都能访问Operation页的List Member页,但我们还是需要修改navigation配置,当这些角色禁止访问list-member资源时,List Member导航项将不再显示:
路径:usr/module/member/config/navigation.php
Code 8.3.4
<?php
return array(
...
'item' => array(
'admin' => array(
'pagea' => array(
'label' => __('List Member'),
'route' => 'admin',
'controller' => 'account',
'action' => 'list',
'resource' => array(
'resource' => 'list-member',
),
),
),
...
),
);
代码中,list-member就是在acl.php里定义的AccountController/listAction对应的资源名。在下一部安装配置介绍完后,就可以进入后台作如下操作:Management->Member模块->Resources导航项->Admin子导航项->Member Admin->List Member Management项选择Denied。再以temporary-member或normal-member角色的帐号进入Opertion页面将会看到List Member导航项被隐藏了(注:这部分的操作如果不明白可以跳过,这里只是介绍导航项的显示/隐藏代码开发,具体操作可参考图8-5,后面的章节将会介绍如何创建帐号并关联角色):
图8-4 禁止访问list-member资源后隐藏导航项
- 安装配置
最后,我们需要在module.php里将这两个需要安装的配置添加上,记住acl配置的添加一定要在page配置之前,否则安装完后,权限的使用会有问题:
路径:usr/module/member/config/module.php
Code 8.3.5
<?php
return array(
...
'maintenance' => array(
'resource' => array(
...
'acl' => 'acl.php',
'page' => 'page.php',
),
),
);
至此就可以重新安装member模块了,安装成功后进入member模块的管理后台,就可以看到角色、资源以权限的对应关系,如图所示。
图8-5 member模块后台资源列表界面
3.3 在后台为用户配置权限
前面的介绍中,我们已经完成了权限后台配置部分的代码,现在用户就可以在后台配置来决定用户对模块Controller & Action的权限,首先我们需要创建几个帐号并为其分配后台角色。进入系统操作后台的Membership页,点击Add a member按钮,如下添加一个帐号并分配其角色为normal-member:
图8-6 创建normal用户并设置角色
以同样的方法创建一个temporary帐号并设置角色为temporary-member。
图8-7 创建的帐号列表
接下来我们需要为member模块的角色分配权限,最基本的要求就是能够看到member模块,也就是为父角色member-admin分配member模块的operation权限,如图所示
图8-8 为member-admin分配member模块的operation权限
这样member-admin的子角色normal-member和temporary-member都可以操作member模块的operation页面,而这两个子角色对operation里的页面的访问权限我们在acl配置里都已经定义好了,即对List Member页面都有访问权限。
图8-9 temporary-member角色访问List Member页
现在用Temporary帐号登陆后台,可以进入List Member页,也能看到所有内容,当点击Delete链接,将会出现如图8-10所示的页面,这是因为我们在配置里禁止temporary-member角色访问delete-member资源(即AccountController/deleteAction):
图8-10 禁止访问delete-member资源
3.4 模块内权限判断开发
在前面的介绍里,我们只需要在后台配置好参数,Pi Engine就会自动帮我们处理是否可以访问该资源,如图8-4、图8-9、图8-10,在之前的需要里,我们希望temporary-member角色不允许看到gender下拉框,同时由于所有模块角色不允许删除用户,所以图8-9中的Delete链接也应该隐藏,这些Pi Engine就无法帮我们做到,开发者需要继续在模块里完成。
- 读取权限并隐藏或显示资源
在前面已经介绍过Pi\Acl\Acl类,我们现在就需要在AccountController/listAction里实例化这个类来获取资源的权限,并将结果赋给模板,模板再决定是否显示或隐藏相关选项。关于Pi\Acl\Acl所有方法的使用可参考Pi文档:
路径:usr/module/member/src/Controller/Admin/AccountController.php
Code 8.3.6
<?php
...
use Pi\Acl\Acl as AclManager;
class AccountController extends ActionController
{
public function listAction()
{
...
$rules = array();
$aclHandler = new AclManager('admin');
$aclHandler->setModule($this->getModule());
$rules['search-by-gender'] = $aclHandler->checkAccess('search-by-gender');
$rules['delete-member'] = $aclHandler->checkAccess('delete-member');
$this->view()->assign('rules', $rules);
$this->view()->assign('items', $items);
}
...
}
由于要实例化Pi\Acl\Acl类,因此在文件开头我们引用了这个类,之后实例化该类,并将section设置为admin;然后通过setModule()方法设置模块为当前模块,即member;由于我们是要判断当前登陆的角色对资源的权限,因此这里就不需要用setRole()方法来设置角色;接着使用checkAccess()方法从数据库里读取当前角色对search-by-gender和delete-member两个资源的权限并将结果赋给$rules变量;最后这个结果赋给模板的rules变量,在模板决定资源的显示与隐藏。
由于delete-member是一个页面资源,因此我们也可以将上面的代码替换成如下代码:
$rules['delete-member'] = $aclHandler->checkAccess(array(
'module' => 'member',
'controller' => 'account',
'action' => 'delete'
));
这种形式就是我们在上面介绍过的用数组来表示资源名的方法。
接下来我们需要修改模板,并让页面显示或隐藏资源:
路径:usr/module/member/template/admin/account-list.phtml
Code 8.3.7
<form action="<?php $this->url('admin', array('action' => 'list')) ?>" method="POST">
<?php if ($rules['search-by-gender']) { ?>
<label><?php echo __('Gender: ') ?></label>
<select name="gender">
<option value="0"><?php echo __('All') ?></option>
<option value="M"><?php echo __('Male') ?></option>
<option value="F"><?php echo __('Female') ?></option>
</select>
<?php } ?>
...
</form>
...
<table>
...
<?php if ($rules['delete-member']) { ?>
<a href="<?php echo $this->url('admin', array('action' => 'delete', 'id' => $item['id'])) ?>"><?php echo __('Delete') ?></a>
<?php } ?>
...
</table>
最终的显示效果如下:
图8-11 模块内权限判断结果