|
本帖最后由 Rabbit_52 于 2013-4-26 00:16 编辑
哈哈,话说一年之后来看这个帖子
权限控制的设计就是分面向模块和面向对象
更新:
前面参照别人的权限验证方法是对控制器和控制器的方法限制不同身份人的权限,但是这样就写死了,用户不能自由分配权限(比如说只允许粉丝看自己的帖子)
但是很多时候权限不是一条线的,从下到上权限递增,是有分支的,比如说bbs的某个会员对于一个版块来说是管理员,但对于另一个版块只是普通会员。
所以我判断是否有权限的思路是,将一个权限分支的权限控制做成数据表存到数据库,比如说有一个post_auth 表
每条权限设置属于一个用户,首先找到请求权限的用户对于当前用户的身份,再同时传入操作去获取是否有该权限
/*
* guest 游客
* register 注册用户
* blocker 帖子主人黑名单
* friend 帖子主人朋友
* self 帖子主人
* admin 管理员
*/
相对于用户来说可能的请求者身份有如上,请求的操作可能有
使用方法 就是在控制器中的某个需要权限验证的方法中调用一次权限验证方法(我是写了一个MY_Controller 包含一个 _auth() 方法 控制器继承MY_Controller )
PHP复制代码 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类,不同的分支的获取身份方法不一样
贴一个帖子权限嘛
PHP复制代码 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[0]['id'];
}
function get_access ($owner_id, $identity, $table) {
$this->jiadb->_table = 'identity';
$result = $this->jiadb->fetchAll(array('name' => $identity));
$identity_id = $result[0]['id'];
$this->jiadb->_table = $table;
$result = $this->jiadb->fetchAll(array('user_id' => $owner_id, 'identity_id' => $identity_id, 'option' => $this->option));
$this->access = $result[0]['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
|
|