onethink的auth权限认证解读(转自TC部落

现在说到权限认证的方式一般都是rbac,onethink使用了扩展的Auth 类来代替rbac作为权限认证的方式。下面我们来看看ot是怎么使用auth类实现其系统的权限认证的。

首先auth类比rbac类更加的可扩展,现在的系统权限认证都是根据url来区分的,程序会根据传入的url来分离出一个标志着此url唯一性的字符串A,然后从数据库中得到该登录用户的权限字符串,如果这个权限字符串中含有这个唯一性的字符串A,那么说明这个用户是可以访问这个url的,说明此用户对于此url是有访问权限的。

rbac作为权限认证方式,他一般只细化到了节点,即mvc菜单控制。如果是比较细化的按钮访问控制就比较麻烦了。而auth是按照规则来进行权限认证的。Auth权限认证是按规则进行认证。我先说说它的原理。 在数据库中我们有 规则表(think_auth_rule) ,用户组表(think_auth_group), 用户组明显表(think_auth_group_access)
我们在规则表中定义权限规则 , 在用户组表中定义每个用户组有哪些权限规则,在用户组明显表中 定义用户所属的用户组。 下面举例说明。
我们要判断用户是否有显示一个操作按钮的权限, 首先定义一个规则, 在规则表中添加一个名为 show_button 的规则。 然后在用户组表添加一个用户组,定义这个用户组有show_button 的权限规则(think_auth_group表中rules字段存得时规则ID,多个以逗号隔开), 然后在用户组明细表定义 UID 为1 的用户 属于刚才这个的这个用户组。

下面我们来看ot的权限检测流程:

首先我们要知道程序是怎么实现权限检测的。从http请求说起,浏览器和服务器的数据交互是通过get和post的方式来进行的,所以url在这里会是非常重要,服务器端通过url来区分客户端的请求,那么就要对这些请求进行权限拦截放行就要依靠url,而url之间是怎么区分的,就是通过url的参数。比如http://www.daydaytc.com/wp-admin/post.php?post=294&action=edit和http://www.daydaytc.com/wp-admin/post.php?post=294&action=add就是两个不同的url,因为其action参数不同,那么服务器端程序就可以对其进行权限判断和拦截,怎么拦截呢?

根据url的形式不同,我们可以把权限分为动态权限和非动态权限。先说非动态权限,这是一种非常常见的权限,这种权限下我们的url是固定设计好的,每个设计好的url对应后台的一个控制器的方法,比如Admin/model/add 和Admin/model/update,这就是两个http://www.daydaytc.com?s=Admin/model/add和http://www.daydaytc.com?s=Admin/model/update  url的权限规则,这样程序就能检测组合出mvc参数,并组合出这个规则,然后通过当前登录用户得到当前用户的所属组,通过组得到组的权限列表,看这个权限规则是否在这个权限列表中,如果在的话说明已授权,不在的话说明没有权限。这就是一个完整的权限设计流程。一般我么处理的也都是这类权限,比如我们后台添加一个菜单,并且给菜单一个控制器方法,然后可以给菜单授权,这个菜单就是一个非动态权限,在我们添加完这个菜单后就会定义这个菜单的mvc参数,这就是规则。

但是我们的系统中并不是只有菜单需要进行权限控制,凡是有url访问入口的都有可能成为权限控制的对象,比如我们新建了一篇文档希望进行权限控制,比如我们新建立了一个分类希望进行权限控制,不可能我们每创建一个分类就为这个分类添加一个节点,更不可能每添加一篇文档就为这篇文档添加一个节点,这样不仅管理麻烦而且节点数量也会爆炸性增长,因此这个时候就需要动态权限控制,需要写一段程序来检测此类url。

下面来看ot是怎么处理动态权限的。

ot的分类授权就是使用这个实现的。

要实现一个完整的权限管理程序的步骤总共分几步:首先创建一个权限规则,第二步为某个用户组授权,第三步在控制器中写入自己的逻辑动态判断权限(根据用户uid会获得所属的用户组,根据用户组获得权限列表,判断现在的id是否在权限列表中。下面来看看ot是怎么通过auth的扩展权限实现分类授权的。

首先其有一张表,auth_extend,里面保存三个字段,分别是组id,数据id和类型id,代表的意思是某个组对某个权限类型的某个数据有权限. 比如对分类授权,分类的类别id就是资源id。

其次是该表的模型类,AuthGroupModel,

里面有个通用的方法addToExtend,主要用来往auth_extend数据表中添加一条数据, static public function addToExtend($gid,$cid,$type)   看传入的三个参数即用户组id,数据id和类型id。

还有一个通用的方法getAuthExtend,主要用来从auth_extend数据表中获取一条数据static public function getAuthExtend($uid,$type,$session)

看分类授权功能编写的步骤:

1: 在后台权限管理页面写入一个分类授权的链接

编辑admin/auth_manager/index.html模板,加入一个<a href=”{:U(‘AuthManager/category?group_name=’.$vo[‘title’].’&group_id=’.$vo[‘id’])}” >分类授权</a>

2:点击上述链接会进入一个页面,在这个页面可以对某个用户组进行类别授权,授权 信息会写入auth_extend表中

此链接指向。

这里编辑admin/auth_manager/category.html

3:  在category.html提交后的控制器代码中使用addToExtend把分类的权限设定写入auth_extend表

4:在控制器中进行权限检测,使用getAuthExtend方法根据用户id,查出用户所属用户组group_id,根据group_id,从auth_extend表以type=1为条件查出了extend_id,即用户拥有权限的分类。

5:当前分类和从查出来的分类数组进行比较,如果存在在数组中说明有权限,没有说明没权限。

下面来看看后台权限判断的流程:

 /**
     * 后台控制器初始化
     */
    protected function _initialize(){
        // 获取当前用户ID
        define('UID',is_login());
        if( !UID ){// 还没登录 跳转到登录页面
            $this->redirect('Public/login');
        }
        /* 读取数据库中的配置 */
        $config =   S('DB_CONFIG_DATA');
        if(!$config){
            $config =   api('Config/lists');
            S('DB_CONFIG_DATA',$config);
        }
        C($config); //添加配置

        // 是否是超级管理员
        define('IS_ROOT',   is_administrator());
        // 检测访问权限
        //调用accessControl方法,该方法是权限检测的第一个指定的方法,在此方法内主要执行的逻辑是特殊节点检测。组合出执行方法的路径方法名称,如果ALLOW_VISIT检测通过,直接放行访问。如果DENY_VISIT检测通过,直接拒绝。如果二者都未通过,则会进入下一步权限检测。
        $access =   $this->accessControl();
        if ( $access === false ) {
            $this->error('403:禁止访问');
        }elseif( $access === null ){
           //checkDynamic方法是执行动态权限,此方法主要用于二次开发的扩展。
            $dynamic        =   $this->checkDynamic();//检测分类栏目有关的各项动态权限
            if( $dynamic === null ){
                //检测非动态权限,这里检测非动态权限的扩展,主要是组合出mvc的执行方法路径,调用auth类的checkrule方法检测权限
                $rule  = strtolower(MODULE_NAME.'/'.CONTROLLER_NAME.'/'.ACTION_NAME);
                if ( !$this->checkRule($rule,array('in','1,2')) ){
                    $this->error('提示:无权访问,您可能需要联系管理员为您授权!');
                }
            }elseif( $dynamic === false ){
                $this->error('提示:无权访问,您可能需要联系管理员为您授权!');
            }
        }
        $this->assign('__controller__', $this);
    }



点赞(0) 打赏

评论列表 共有 0 条评论

暂无评论

微信小程序

微信扫一扫体验

立即
投稿

微信公众账号

微信扫一扫加关注

发表
评论
返回
顶部