thinkPHP3.2使用RBAC实现权限管理的实现


Posted in PHP onAugust 27, 2019

在thinkphp3.2中自己集成了RBAC来实现权限管理,RBAC实现类在项目中地址为:ThinkPHP/Librar/Org/Util/Rbac.class.php,其中集成了我们所需的权限管理操作

一:表设计

在thinkPHP的Rbac的的Rbac.class.php文件中一共提供了4张表,还有一张用户表需要你自己去建

如下是我所建的和权限相关的sql

其中的wj_为表前缀,改成你项目中的表前缀

1:权限表:

CREATE TABLE IF NOT EXISTS `wj_access` (
 `role_id` SMALLINT(6) UNSIGNED NOT NULL COMMENT '角色ID',
 `node_id` SMALLINT(6) UNSIGNED NOT NULL COMMENT '节点ID',
 `level` TINYINT(1) NOT NULL COMMENT '深度',
 `module` VARCHAR(50) DEFAULT NULL COMMENT '模块',
 KEY `groupId` (`role_id`),
 KEY `nodeId` (`node_id`)
) ENGINE=MYISAM DEFAULT CHARSET=utf8 COMMENT='权限表';

2:节点表:

CREATE TABLE IF NOT EXISTS `wj_node` (
 `id` SMALLINT(6) UNSIGNED NOT NULL AUTO_INCREMENT COMMENT '节点ID',
 `name` VARCHAR(20) NOT NULL COMMENT '节点名称',
 `title` VARCHAR(50) DEFAULT NULL COMMENT '节点标题',
 `status` TINYINT(1) DEFAULT '0' COMMENT '状态 0禁用 1启用',
 `remark` VARCHAR(255) DEFAULT NULL COMMENT '描述',
 `sort` SMALLINT(6) UNSIGNED DEFAULT NULL COMMENT '排序',
 `pid` SMALLINT(6) UNSIGNED NOT NULL COMMENT '父级节点',
 `level` TINYINT(1) UNSIGNED NOT NULL COMMENT '深度',
 PRIMARY KEY (`id`),
 KEY `level` (`level`),
 KEY `pid` (`pid`),
 KEY `status` (`status`),
 KEY `name` (`name`)
) ENGINE=MYISAM DEFAULT CHARSET=utf8 COMMENT='节点表';

3:用户角色表:

CREATE TABLE IF NOT EXISTS `wj_role` (
 `id` SMALLINT(6) UNSIGNED NOT NULL AUTO_INCREMENT COMMENT '角色ID',
 `name` VARCHAR(20) NOT NULL COMMENT '角色名称',
 `pid` SMALLINT(6) DEFAULT NULL '父级ID',
 `status` TINYINT(1) UNSIGNED DEFAULT NULL COMMENT '状态 0禁用 1启用',
 `remark` VARCHAR(255) DEFAULT NULL COMMENT '备注',
 PRIMARY KEY (`id`),
 KEY `pid` (`pid`),
 KEY `status` (`status`)
) ENGINE=MYISAM DEFAULT CHARSET=utf8 COMMENT='用户角色表';

4:用户角色关联表:

CREATE TABLE IF NOT EXISTS `wj_role_user` (
 `role_id` MEDIUMINT(9) UNSIGNED DEFAULT NULL COMMENT '角色ID',
 `user_id` CHAR(32) DEFAULT NULL COMMENT '用户ID',
 KEY `group_id` (`role_id`),
 KEY `user_id` (`user_id`)
) ENGINE=MYISAM DEFAULT CHARSET=utf8 COMMENT='用户角色关联表';

5:用户表:

CREATE TABLE IF NOT EXISTS `wj_user` (
 `user_id` INT(11) UNSIGNED NOT NULL AUTO_INCREMENT COMMENT '用户ID',
 `username` VARCHAR(50) NOT NULL COMMENT '用户名',
 `password` VARCHAR(100) NOT NULL COMMENT '密码',
 `create_time` INT(10) DEFAULT NULL COMMENT '创建时间',
 `update_time` INT(10) DEFAULT NULL COMMENT '更新时间',
 `status` INT(1) DEFAULT NULL COMMENT '状态 0禁用 1启用',
 PRIMARY KEY (`user_id`)
) ENGINE=MYISAM DEFAULT CHARSET=utf8 COMMENT='用户表';

二:关于权限操作的常用配置:

你可以在config.php文件的数组中增加:

// 加载扩展配置文件
'LOAD_EXT_CONFIG' => 'user',

这样的话我们就可以将我们的所有权限配置放置在config.php同级的user.php文件中,user.php文件配置如下:

<?php
/**
 * 用户权限配置文件
 */
return array(
  // 是否需要认证
  'USER_AUTH_ON' => true,
  // 认证类型 1 登录认证 2 实时认证
  'USER_AUTH_TYPE' => 1,
  // 后台用户认证SESSION标记
  'USER_AUTH_KEY' => 'wjAuthId',
  // 默认认证网关
  'USER_AUTH_GATEWAY' => '?m=Admin&c=Login&a=index',
  // RBAC_DB_DSN 数据库连接DSN
  // 角色表名称,C('DB_PREFIX')表示前缀
  'RBAC_ROLE_TABLE' => C('DB_PREFIX') . 'role',
  // 用户角色关联表名称
  'RBAC_USER_TABLE' => C('DB_PREFIX') . 'role_user',
  // 权限表名称
  'RBAC_ACCESS_TABLE' => C('DB_PREFIX') . 'access',
  // 节点表名称
  'RBAC_NODE_TABLE' => C('DB_PREFIX') . 'node',
  // 默认验证数据表模型
  'USER_AUTH_MODEL' => 'User',
  // 超级管理员的SESSION标记
  'ADMIN_AUTH_KEY' => 'wjAdministrator',
  // 默认需要认证模块
  'REQUIRE_AUTH_MODULE' => '',
  // 默认需要认证操作
  'REQUIRE_AUTH_ACTION' => '',
  // 默认无需认证模块
  'NOT_AUTH_MODULE' => 'Public',
  // 默认无需认证操作
  'NOT_AUTH_ACTION' => '',
  // 是否开启游客授权访问
  'GUEST_AUTH_ON' => false,
  // 游客的用户ID
  'GUEST_AUTH_ID' => 0,
  // 后台用户名的SESSION标记
  'BACK_LOGIN_NAME' => 'loginBackName',
  // 后台角色的SESSION标记
  'BACK_USER_ROLE' => 'bakcUserRole',
  // 后台角色ID的SESSION标记
  'BACK_ROLE_ID' => 'backRoleId',
  // 后台用户登录时间的SESSION标记
  'BACK_ONLINE_TIME' => 'backOnlineTime',
  // 后台在线间隔时间,以分钟为单位
  'ONLINE_INTERVAL' => 180,
  //退出登录的URL
  'LOGOUT_URL' => '/test',
);

三:关于权限操作的常用方法:

1:Rbac::saveAccessList($authId=null);

缓存权限列表,在这个方法可以传递空值的前提是:你在用户登录操作的时候要在 $_SESSION[C('USER_AUTH_KEY')] 中把用户的id保存下来,然后这里会将用户所对应的角色拥有的权限都保存在$_SESSION['_ACCESS_LIST']中

2:Rbac::checkAccess()

判断用户访问的模块和方法是否需要权限认证

3:Rbac::AccessDecision()

断用户是否有访问权限的,即检测当前项目模块操作 是否在$_SESSION['_ACCESS_LIST']数组中,也就是说 在 $_SESSION['_ACCESS_LIST'] 数组中$_SESSION'_ACCESS_LIST''当前控制器'是否存在。如果存在表示有权限 否则返回flase

4:Rbac::checkLogin();

判断用户是否登录,如果未登录则跳转到指定路径

5:Rbac::getAccessList($authId)

通过查询数据库 返回权限列表 $_SESSION['_ACCESS_LIST']的值

6:Rbac::authenticate($map, $model='')

传入查询用户的条件和用户表的MODEL 返回数组包含用户的信息,如果不传model值的话使用配置项中的USER_AUTH_MODEL

四:权限管理简单实现实例:

1:登录:

//获取传递的用户名和密码
$username = I('post.username');
$password = I('post.password');
//生成认证条件
$map = array();
$map['username'] = $username;
$map['status'] = array('eq', 1);
//判断是否存在此用户
$authInfo = Rbac::authenticate($map);
if (!$authInfo) {
  $this->error('账号不存在');
}
if ($authInfo['password'] != md5($password)) {
  $this->error('密码错误');
}
$user_id = $authInfo['user_id'];
$role_user = new Model();
$role = $role_user->Table(C("RBAC_USER_TABLE"))->alias("user")->where("user_id=" . $user_id)->join(C("RBAC_ROLE_TABLE") . " as role ON role.id=user.role_id")->field("id,name")->find();
if (empty($role)) {
  $this->error('此用户无对应的角色,无法登录');
}
//后台角色ID的SESSION标记
session(C('BACK_ROLE_ID'), $role['id']);
//后台角色的SESSION标记
session(C('BACK_USER_ROLE'), $role['name']);
//后台用户认证SESSION标记
session(C('USER_AUTH_KEY'), $authInfo['user_id']);
//后台用户名的SESSION标记
session(C('BACK_LOGIN_NAME'), $authInfo['username']);
//后台用户登录时间的SESSION标记
session(C('BACK_ONLINE_TIME'), time());
//判断用户角色是否为超级管理员
if ($role['id'] == '1') {
  //超级管理员将超级管理员的SESSION标记设置为true
  session(C('ADMIN_AUTH_KEY'), true);
}
// 缓存访问权限
Rbac::saveAccessList();
$this->success('登录成功', U('Index/index'));

2:登录成功后的权限校验:

//验证是否登录
Rbac::checkLogin();
// 用户权限检查
if (Rbac::checkAccess() && !Rbac::AccessDecision()) {
  // 没有权限 清除登录session 并抛出错误
  if (C('RBAC_ERROR_PAGE')) {
    // 定义权限错误页面
    redirect(C('RBAC_ERROR_PAGE'));
  } else {
    if (C('GUEST_AUTH_ON')) {
      //开启游客访问
    }
    // 提示错误信息
    $this->error(L('_VALID_ACCESS_'));
  }
}
//自动退出功能,判断后台用户登录时间的SESSION标记是否超时
if (session(C('BACK_ONLINE_TIME')) + C('ONLINE_INTERVAL') * 60 < time()) {
  if (session('?' . C('USER_AUTH_KEY'))) {
    session('[destroy]');
    if (isset($_COOKIE[session_name()])) {
      setcookie(session_name(), '', time() - 3600, '/');
    }
    session_destroy();
  }
  $this->error('超时请重新登录', U('Login/index'));
} else {
  session(C('BACK_ONLINE_TIME'), time());
}

根据如上就可以实现用户角色的权限管理

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持三水点靠木。

PHP 相关文章推荐
一个简单的PHP投票程序源码
Mar 11 PHP
用来给图片加水印的PHP类
Apr 09 PHP
PHP实现域名whois查询的代码(数据源万网、新网)
Feb 22 PHP
让你成为更出色的PHP开发者的10个技巧
Feb 25 PHP
php笔记之:数据类型与常量的使用分析
May 14 PHP
深入PHP与浏览器缓存的分析
Jun 03 PHP
php5.3 goto函数介绍和示例
Mar 21 PHP
PHP类中的魔术方法(Magic Method)简明总结
Jul 08 PHP
php中PDO方式实现数据库的增删改查
May 17 PHP
php实现粘贴截图并完成上传功能
May 17 PHP
Zend Framework教程之连接数据库并执行增删查的方法(附demo源码下载)
Mar 21 PHP
替换php字符串中的单引号为双引号的方法
Feb 16 PHP
PHP如何将图片文件上传到另外一台服务器上
Aug 26 #PHP
PHP命名空间与自动加载机制的基础介绍
Aug 25 #PHP
php的命名空间与自动加载实现方法
Aug 25 #PHP
PHP7数组的底层实现示例
Aug 25 #PHP
PHP实现cookie跨域session共享的方法分析
Aug 23 #PHP
php常用经典函数集锦【数组、字符串、栈、队列、排序等】
Aug 23 #PHP
php中错误处理操作实例分析
Aug 23 #PHP
You might like
模仿OSO的论坛(四)
2006/10/09 PHP
php a simple smtp class
2007/11/26 PHP
浅析php变量修饰符static的使用
2013/06/28 PHP
关于php内存不够用的快速解决方法
2013/10/26 PHP
Yii中srbac权限扩展模块工作原理与用法分析
2016/07/14 PHP
关于IFRAME 自适应高度的研究
2006/07/20 Javascript
js focus不起作用的解决方法(主要是因为dom元素是否加载完成)
2010/11/05 Javascript
javascript实现的弹出层背景置灰-模拟(easyui dialog)
2013/12/27 Javascript
JavaScript获取Url里的参数
2014/12/18 Javascript
javascript显式类型转换实例分析
2015/04/25 Javascript
在一个页面重复使用一个js函数的方法详解
2016/12/26 Javascript
Vue.js结合bootstrap实现分页控件
2017/03/10 Javascript
React-router 4 按需加载的实现方式及原理详解
2017/05/25 Javascript
react-native之ART绘图方法详解
2017/08/08 Javascript
微信小程序之选项卡的实现方法
2017/09/29 Javascript
JS实现盒子跟着鼠标移动及键盘方向键控制盒子移动效果示例
2019/01/29 Javascript
layui table设置某一行的字体颜色方法
2019/09/05 Javascript
JS对象属性的检测与获取操作实例分析
2020/03/17 Javascript
Js生成随机数/随机字符串的方法小结【5种方法】
2020/05/27 Javascript
bootstrap-table后端分页功能完整实例
2020/06/01 Javascript
Openlayers+EasyUI Tree动态实现图层控制
2020/09/28 Javascript
Python中非常实用的一些功能和函数分享
2015/02/14 Python
Python正则捕获操作示例
2017/08/19 Python
Python中应该使用%还是format来格式化字符串
2018/09/25 Python
python 解决动态的定义变量名,并给其赋值的方法(大数据处理)
2018/11/10 Python
Python selenium根据class定位页面元素的方法
2019/02/26 Python
由面试题加深对Django的认识理解
2019/07/19 Python
Pyecharts 动态地图 geo()和map()的安装与用法详解
2020/03/25 Python
使用python实现名片管理系统
2020/06/18 Python
新大陆软件面试题
2016/11/24 面试题
销售行政专员职责
2014/01/03 职场文书
教师学习群众路线心得体会
2014/11/04 职场文书
指导老师鉴定意见
2015/06/05 职场文书
spring boot项目application.properties文件存放及使用介绍
2021/06/30 Java/Android
TV动画《八十龟酱观察日记》第四季宣传PV公布
2022/04/06 日漫
详解Mysql数据库平滑扩容解决高并发和大数据量问题
2022/05/25 MySQL