欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  php教程

RBAC在PHP中的应用

程序员文章站 2022-05-19 12:57:50
...

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

关于用户权限,有几种不同的处理方法,如位运算和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语句:

查看源代码 打印帮助

01 CREATE 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

07 CREATE 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

13 CREATE 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

20 CREATE 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是一个返回赋予了相关权限的角色类。并可以检测相关权限的可用状态。

查看源代码 打印帮助

01 class 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

查看源代码 打印帮助

01 class 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 }

简单的使用代码:

查看源代码 打印帮助

01 include_once('User.php');

02 include_once('Role.php');

03 include_once('PrivilegedUser.php');

04

05 $GLOBALS['DB'] = new PDO('mysql:host=localhost;dbname=dbname', 'root', '');

06

07 session_start();

08 // 根据自己的程序设置下面的session

09 if(isset($_SESSION['loggedin'])){

10 // 获取相应的角色权限

11 $u = PrivilegedUser::getByUsername('lijing');

12 }

13

14 // 如果存在权限进行什么操作

15 if($u->hasPrivilege('primission')){

16 // action code here

17 }

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

查看源代码 打印帮助

01 // 添加角色名称

02 public 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 // 为用户添加角色

08 public 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 // 删除角色和相关权限

19 public 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 // 删除用户的角色

32 public 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 // 检查用户是否具有特殊角色

02 public function hasRole($role_name) {

03 return isset($this->roles[$role_name]);

04 }

05

06 // 添加一个权限

07 public 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 // 删除所有权限角色

14 public static function deletePerms() {

15 $sql = "TRUNCATE role_perm";

16 $sth = $GLOBALS["DB"]->prepare($sql);

17 return $sth->execute();

18 }

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