RBAC在PHP中的应用

关于用户权限,有几种不同的处理方法,如位运算和ACL,他们都各有千秋。
使用位运算控制权限,由于在计算机中只允许位移次数在32或64次之间,所有权限最多只能有32-64位。
位运算控制权限资料链接:链接1备用链接

http://xiaobin.net/200906/bitwise-permission/

http://www.cnblogs.com/toby/archive/2011/10/23/2221863.html

使用访问控制列表(ACL:access control list),但是这种方法只允许向对象分配权限,而无法使对象进行一些特殊的操作。
本文讲述的是“基于角色的访问控制”(RBAC:role based access control)。
用户通过赋予不同的角色来得到相关的权限,不同的角色又可以分配不同的权限。因此权限分配非常灵活。
但是缺点是,如果没有很好的对权限和角色进行组织,那么系统将会变得非常混乱。

RBAC的实现过程

数据库设计,RBAC的实现过程需要5张表:角色表、权限表、角色权限关联表、用户角色关联表、用户表。
其中用户表根据自己的项目进行设定,本文中不提供设计数据库的sql语句了,只使用到用户表中的位移id(user_id)。
几个表内容如下:

roles(角色)                      存储role id, role name
permissions(权限)       存储permission id, description
role_perm                      存储角色和权限的关联表role_id, perm_id
user_role                        存储用户和角色的关联表user_id, role_id

下面是建表SQL语句:

01CREATE TABLE roles (
02  role_id INTEGER UNSIGNED NOT NULL AUTO_INCREMENT,
03  role_name VARCHAR(50) NOT NULL,
04  PRIMARY KEY (role_id)
05);
06  
07CREATE TABLE permissions (
08  perm_id INTEGER UNSIGNED NOT NULL AUTO_INCREMENT,
09  perm_name VARCHAR(50) NOT NULL,
10  PRIMARY KEY (perm_id)
11);
12  
13CREATE TABLE role_perm (
14  role_id INTEGER UNSIGNED NOT NULL,
15  perm_id INTEGER UNSIGNED NOT NULL,
16  FOREIGN KEY (role_id) REFERENCES roles(role_id),
17  FOREIGN KEY (perm_id) REFERENCES permissions(perm_id)
18);
19  
20CREATE TABLE user_role (
21  user_id INTEGER UNSIGNED NOT NULL,
22  role_id INTEGER UNSIGNED NOT NULL,
23  FOREIGN KEY (user_id) REFERENCES users(user_id),
24  FOREIGN KEY (role_id) REFERENCES roles(role_id)
25);

默认情况下我们不需要对用户表中的用户进行角色分配,根据你自己的项目,写个sql来给用户进行添加角色,或者在privilegedUser类中对用户初始化一个空权限的角色。

Role Class – [Role.php]

Role是一个返回赋予了相关权限的角色类。并可以检测相关权限的可用状态。

01class Role{
02    protected $permission;
03  
04    protected function __construct(){
05        $this->permission = array();
06    }
07  
08    // 返回一个综合权限的对象
09    public static function getRolePerms($role_id){
10        $role = new Role();
11        $sql = "SELECT t2.perm_name FROM role_perm as t1
12                JOIN permisssions as t2 ON t1.perm_id = t2.perm_id
13                WHERE t1.role_id = :role_id";
14        $sth = $GLOBALS['DB']->prepare($sql);
15        $sth->execute(array(":role_id" => $role_id));
16        while($row = $sth->fetch(PDO::FETCH_ASSOC)){
17            $role->permission[$row["perm_name"]] = TRUE;
18        }
19        return $role;
20    }
21  
22    // 检查是否具有权限
23    public function hasPerm($permission){
24        return isset($this->permission[$permission]);
25    }
26}
Privilege User Class

这个可以集成你的User类,在新的方法中为user对象赋予新的属性。
方法initRoles()获取角色,并得到相关权限。

privilegedUser.php

01class PrivilegedUser extends User{
02    private $roles;
03  
04    public function __construct(){
05        parent::__construct();
06    }
07  
08    public static function getByUsername($username){
09        $sql = "SELECT * FROM users WHERE username = :username";
10        $sth = $GLOBALS['DB']->prepare($sql);
11        $sth->execute(array(":username" => $username));
12        $result = $sth->fetchAll();
13  
14        if(!empty($result)){
15            $privUser = new PrivilegedUser();
16            $privUser->user_id = $result[0]["user_id"];
17            $privUser->username = $username;
18            $privUser->password = $result[0]["password"];
19            $privUser->email = $result[0]["email"];
20            $privUser->initRoles();
21            return $privUser;
22        }else{
23            return FALSE;
24        }
25    }
26  
27    // 获取角色,并得到相关权限
28    protected function initRoles(){
29        $this->roles = array();
30        $sql = "SELECT t1.role_id, t2.role_name FROM user_role AS t1
31                JOIN roles AS t2 ON t1.role_id = t2.role_id
32                WHERE t1.user_id = :user_id";
33        $sth = $GLOBALS["DB"]->prepare($sql);
34        $sth->execute(array(":user_id" => $this->user_id));
35  
36        while($row = $sth->fetch(PDO::FETCH_ASSOC)){
37            $this->roles[$row['role_name']] = Role::getRolePerms($row["role_id"]);
38        }
39    }
40  
41    // 判断特殊权限
42    public function hasPrivilege($perm){
43        foreach($this->row as $row){
44            if($role->hasperm($perm)){
45                return TRUE;
46            }
47        }
48        return FALSE;
49    }
50}

简单的使用代码:

01include_once('User.php');
02include_once('Role.php');
03include_once('PrivilegedUser.php');
04  
05$GLOBALS['DB'] = new PDO('mysql:host=localhost;dbname=dbname', 'root', '');
06  
07session_start();
08// 根据自己的程序设置下面的session
09if(isset($_SESSION['loggedin'])){
10    // 获取相应的角色权限
11    $u = PrivilegedUser::getByUsername('lijing');
12}
13  
14// 如果存在权限进行什么操作
15if($u->hasPrivilege('primission')){
16    // action code here
17}

代码增强:
以下代码主要为了更好的管理角色权限。将这些方法根据需求放入自己的项目(Role.php)中。

01// 添加角色名称
02public static function insertRole($role_name){
03    $sql = "INSERT INTO roles(role_name) VALUES (:role_name)";
04    $sth = $GLOBALS['DB']->prepare($sql);
05    return $sth->execute(array(":role_name" => $role_name));
06}
07// 为用户添加角色
08public static function insertUserRoles($user_id, $roles){
09    $sql = "INSERT INTO user_role(user_id, role_id) VALUES(:user_id, :role_id)";
10    $sth = $GLOBALS['DB']->prepare($sql);
11    $sth->bindParam(":user_id", $user_id, PDO::PARAM_STR);
12    $sth->bindParam(":role_id", $role_id, PDO::PARAM_STR);
13    foreach($roles as $role_id){
14        $sth->execute();
15    }
16    return true;
17}
18// 删除角色和相关权限
19public static function deleteRoles($roles) {
20    $sql = "DELETE t1, t2, t3 FROM roles as t1
21            JOIN user_role as t2 on t1.role_id = t2.role_id
22            JOIN role_perm as t3 on t1.role_id = t3.role_id
23            WHERE t1.role_id = :role_id";
24    $sth = $GLOBALS["DB"]->prepare($sql);
25    $sth->bindParam(":role_id", $role_id, PDO::PARAM_INT);
26    foreach ($roles as $role_id) {
27        $sth->execute();
28    }
29    return true;
30}
31// 删除用户的角色
32public static function deleteUserRoles($user_id) {
33    $sql = "DELETE FROM user_role WHERE user_id = :user_id";
34    $sth = $GLOBALS["DB"]->prepare($sql);
35    return $sth->execute(array(":user_id" => $user_id));
36}

把下面的方法加入到privilegedUser类中

01// 检查用户是否具有特殊角色
02public function hasRole($role_name) {
03    return isset($this->roles[$role_name]);
04}
05  
06// 添加一个权限
07public static function insertPerm($role_id, $perm_id) {
08    $sql = "INSERT INTO role_perm (role_id, perm_id) VALUES (:role_id, :perm_id)";
09    $sth = $GLOBALS["DB"]->prepare($sql);
10    return $sth->execute(array(":role_id" => $role_id, ":perm_id" => $perm_id));
11}
12  
13// 删除所有权限角色
14public static function deletePerms() {
15    $sql = "TRUNCATE role_perm";
16    $sth = $GLOBALS["DB"]->prepare($sql);
17    return $sth->execute();
18}

也可以添加自己的角色权限管理方法。

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值