Skip to content

Tutorial.Authentication Management II.zh_cn

liuchuangww edited this page Jul 4, 2013 · 2 revisions

English

  1. 在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。待其他文件都完成后,重新安装就可以在后台看到创建的角色,及其继承关系:

fig8-3

图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,后面的章节将会介绍如何创建帐号并关联角色):

fig8-4

图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模块的管理后台,就可以看到角色、资源以权限的对应关系,如图所示。

fig8-5

图8-5 member模块后台资源列表界面

3.3 在后台为用户配置权限

前面的介绍中,我们已经完成了权限后台配置部分的代码,现在用户就可以在后台配置来决定用户对模块Controller & Action的权限,首先我们需要创建几个帐号并为其分配后台角色。进入系统操作后台的Membership页,点击Add a member按钮,如下添加一个帐号并分配其角色为normal-member:

fig8-6

图8-6 创建normal用户并设置角色

以同样的方法创建一个temporary帐号并设置角色为temporary-member。

fig8-7

图8-7 创建的帐号列表

接下来我们需要为member模块的角色分配权限,最基本的要求就是能够看到member模块,也就是为父角色member-admin分配member模块的operation权限,如图所示

fig8-8

图8-8 为member-admin分配member模块的operation权限

这样member-admin的子角色normal-member和temporary-member都可以操作member模块的operation页面,而这两个子角色对operation里的页面的访问权限我们在acl配置里都已经定义好了,即对List Member页面都有访问权限。

fig8-9

图8-9 temporary-member角色访问List Member页

现在用Temporary帐号登陆后台,可以进入List Member页,也能看到所有内容,当点击Delete链接,将会出现如图8-10所示的页面,这是因为我们在配置里禁止temporary-member角色访问delete-member资源(即AccountController/deleteAction):

fig8-10

图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>

最终的显示效果如下:

fig8-11

图8-11 模块内权限判断结果

Clone this wiki locally