Rabbit_52 发表于 2012-3-28 17:07:55

一个权限控制的思路,参考各位大神的,求评价

本帖最后由 Rabbit_52 于 2013-4-26 00:16 编辑

哈哈,话说一年之后来看这个帖子
权限控制的设计就是分面向模块和面向对象

更新:

前面参照别人的权限验证方法是对控制器和控制器的方法限制不同身份人的权限,但是这样就写死了,用户不能自由分配权限(比如说只允许粉丝看自己的帖子)

但是很多时候权限不是一条线的,从下到上权限递增,是有分支的,比如说bbs的某个会员对于一个版块来说是管理员,但对于另一个版块只是普通会员。

所以我判断是否有权限的思路是,将一个权限分支的权限控制做成数据表存到数据库,比如说有一个post_auth 表



每条权限设置属于一个用户,首先找到请求权限的用户对于当前用户的身份,再同时传入操作去获取是否有该权限
/*
         *guest 游客
         *register 注册用户
         *blocker 帖子主人黑名单
         *friend 帖子主人朋友
         *self 帖子主人
         *admin 管理员
         */


相对于用户来说可能的请求者身份有如上,请求的操作可能有


使用方法 就是在控制器中的某个需要权限验证的方法中调用一次权限验证方法(我是写了一个MY_Controller 包含一个 _auth() 方法 控制器继承MY_Controller )

require_once APPPATH . 'libraries/jiadb.php';
require_once APPPATH . 'libraries/auth.php';
require_once APPPATH . 'libraries/user.php';
      class MY_Controller extends CI_Controller {
                public $jiadb;
                function __construct() {
                        parent::__construct();
                        $this->jiadb = new Jiadb('users');
                }
               
                function _auth($option, $type, $param = '') {
                        $auth = Auth_factory::get_auth($option, $type, $param);
                        if(!$auth->access) {
                              show_error('No Right to Access');
                        }
                }
      }

因为我的项目有三个权限分支(帖子,活动,社团)为了方便写了一个auth类,不同的分支的获取身份方法不一样

贴一个帖子权限嘛

class Auth {
                // 请求权限的用户
                public $request_user;
                // 请求的操作
                public $option;
                // 权限值
                public $access;
                public $jiadb;
                public $CI;
                function __construct($option) {
                        $this->access = 0;
                        $this->request_user = $this->CI->session->userdata('id');
                        $this->CI =& get_instance();
                        $this->jiadb = new Jiadb('options');
                        // option(name) => option(id)
                        $result = $this->jiadb->fetchAll(array('name' => $option));
                        $this->option = $result['id'];
                }
               
                function get_access($owner_id, $identity, $table) {
                        $this->jiadb->_table = 'identity';
                        $result = $this->jiadb->fetchAll(array('name' => $identity));
                        $identity_id = $result['id'];
                        $this->jiadb->_table = $table;
                        $result = $this->jiadb->fetchAll(array('user_id' => $owner_id, 'identity_id' => $identity_id, 'option' => $this->option));
                        $this->access = $result['access'];
                }
      }
class Post_auth extends Auth {
                public $post;
                public $table;
                function __construct($option, $post = '') {
                        parent::__construct($option);
                        $this->post = $post;
                        $this->table = 'post_auth';
                }
               
                function get_access() {
                        $owner_id = $this->post['user_id'];
                        $identity = '';
                        // 游客
                        if($this->CI->session->userdata('type') == 'guest') {
                              $identity = 'guest';
                              parent::get_access($owner_id, $identity, $this->table);
                              if($this->access == 1) {
                                        return;
                              }
                        }
                        $owner = new User($owner_id);
                        // 黑名单
                        $blockers = $owner->get_blockers();
                        if(in_array($this->request_user, $friends)) {
                              $identity = 'blocker';
                              parent::get_access($owner_id, $identity, $this->table);
                              return;
                        }
                        // 注册用户
                        if($this->CI->session->userdata('type') == 'register') {
                              $identity = 'register';
                              parent::get_access($owner_id, $identity, $this->table);
                              if($this->access == 1) {
                                        return;
                              }
                        }
                        // 朋友
                        $friends = $owner->get_friends();
                        if(in_array($this->request_user, $friends)) {
                              $identity = 'friend';
                              parent::get_access($owner_id, $identity, $this->table);
                              if($this->access) {
                                        return;
                              }
                        }
                        $user = new User($this->request_user);
                        // 本人
                        if($this->post['user_id'] == $this->request_user) {
                              $identity = 'self';
                              parent::get_access($owner_id, $identity, $this->table);
                              if($this->access) {
                                        return;
                              }
                        }
                        // 验证是否管理员
                        if($this->CI->session->userdata('type') == 'admin') {
                              $this->access = 1;
                              return;
                        }
                }
      }

个人感觉这样的代码不是很优雅~但是没得法,求各位大大提点意见
---------------------------------------------------------------------------
思路:
当需要执行需要权限验证的操作时,先通过hook判断对某个控制器的某个方法是否拥有权限(比如说管理员对所有帖子拥有编辑删除权限),再通过控制器内置方法对特定权限进行权限判断(比如说某个帖子的发帖者对它的帖子有编辑权限)

具体实现:
hook的pre_controller 挂钩点
全局变量 $RTR (CI 路由对象)能获取请求的控制器名以及方法名

Controller的 _remap($method, $param)
能获取请求的方法名以及所传参数,可以写一个MY_Controller 适当继承,根据不同情况适当重写

参考了帖子http://codeigniter.org.cn/forums/thread-4374-1-1.html


thankwsx 发表于 2012-3-28 17:12:34

hook是什么?
类似python里面的decorator那样的?

Rabbit_52 发表于 2012-3-28 17:14:21

thankwsx 发表于 2012-3-28 17:12 static/image/common/back.gif
hook是什么?
类似python里面的decorator那样的?

hook就是CI的钩子嘛~

kuailewang 发表于 2012-4-6 11:48:05

可不可以共享一下唉 急需要 万分感谢楼主

Rabbit_52 发表于 2012-4-6 12:05:27

kuailewang 发表于 2012-4-6 11:48 static/image/common/back.gif
可不可以共享一下唉 急需要 万分感谢楼主

现在项目还不是很完善,我放在google project上面的
https://code.google.com/p/jia2/

kuailewang 发表于 2012-4-10 10:54:00

Rabbit_52 发表于 2012-4-6 12:05 static/image/common/back.gif
现在项目还不是很完善,我放在google project上面的
https://code.google.com/p/jia2/

谢谢 :victory:

kuailewang 发表于 2012-4-10 11:02:16

Rabbit_52 发表于 2012-4-6 12:05 static/image/common/back.gif
现在项目还不是很完善,我放在google project上面的
https://code.google.com/p/jia2/

require_once APPPATH . 'libraries/jiadb.php';
require_once APPPATH . 'libraries/auth.php';
require_once APPPATH . 'libraries/user.php';

这几个文件没有啊?

Rabbit_52 发表于 2012-4-11 09:15:53

kuailewang 发表于 2012-4-10 11:02 static/image/common/back.gif
require_once APPPATH . 'libraries/jiadb.php';
require_once APPPATH . 'libraries/auth.php';
require ...

你checkout新版的呢,那个user是没有了,但是其他的都在libraries目录下

Rabbit_52 发表于 2012-4-12 10:47:27

heykite 发表于 2012-4-12 10:03 static/image/common/back.gif
自从两个妓女自称是某名牌大学的毕业生后,我现在一般都自称文盲! 




哥们儿,你咋回事 =.=

testabc111 发表于 2012-4-20 17:26:49

思路没错,我们开发系统也差不多类似的思路。

总得来说,可以分为URI的权限和细节权限。

URI的权限可以在pre_controller用钩子判断,而细节权限则要根据具体项目来做了,就像你说的,同一条URI,同一个人在不同的帖子面前,有时候只可以读,有时候即可读又可写。
页: [1] 2 3
查看完整版本: 一个权限控制的思路,参考各位大神的,求评价