RBAC类使用
1.实现
首先我们先简单理解一下RBAC,顾名思义,RBAC是基于角色的权限设计。既然根据角色去分权限,那么我们就得有角色表,权限表,角色对应权限表,这是最基本的。角色是什么,就是你的身份,你的职位,也就是一个用户拥有这个身份才能获得某种权力。插一句,角色下辖的是用户,一个角色组可以有多个用户,一个用户也可能有多个角色,多对多的关系。
打开RBAC.class.php,你会发现官方已经告诉你,需要准备的东西。首先是配置文件需要设置的东西如下:
- // 配置文件增加设置
- // USER_AUTH_ON 是否需要认证
- // USER_AUTH_TYPE 认证类型 1 登录认证 2 实时认证
- // USER_AUTH_KEY 认证识别号
- // REQUIRE_AUTH_MODULE 需要认证模块
- // NOT_AUTH_MODULE 无需认证模块
- // USER_AUTH_GATEWAY 认证网关
- // RBAC_DB_DSN 数据库连接DSN
- // RBAC_ROLE_TABLE 角色表名称
- // RBAC_USER_TABLE 用户表名称
- // RBAC_ACCESS_TABLE 权限表名称
- // RBAC_NODE_TABLE 节点表名称
- /*
- -- --------------------------------------------------------
- CREATE TABLE IF NOT EXISTS `think_access` (
- `role_id` smallint(6) unsigned NOT NULL,
- `node_id` smallint(6) unsigned NOT NULL,
- `level` tinyint(1) NOT NULL,
- `module` varchar(50) DEFAULT NULL,
- KEY `groupId` (`role_id`),
- KEY `nodeId` (`node_id`)
- ) ENGINE=MyISAM DEFAULT CHARSET=utf8;
- CREATE TABLE IF NOT EXISTS `think_node` (
- `id` smallint(6) unsigned NOT NULL AUTO_INCREMENT,
- `name` varchar(20) NOT NULL,
- `title` varchar(50) DEFAULT NULL,
- `status` tinyint(1) DEFAULT '0',
- `remark` varchar(255) DEFAULT NULL,
- `sort` smallint(6) unsigned DEFAULT NULL,
- `pid` smallint(6) unsigned NOT NULL,
- `level` tinyint(1) unsigned NOT NULL,
- PRIMARY KEY (`id`),
- KEY `level` (`level`),
- KEY `pid` (`pid`),
- KEY `status` (`status`),
- KEY `name` (`name`)
- ) ENGINE=MyISAM DEFAULT CHARSET=utf8;
- CREATE TABLE IF NOT EXISTS `think_role` (
- `id` smallint(6) unsigned NOT NULL AUTO_INCREMENT,
- `name` varchar(20) NOT NULL,
- `pid` smallint(6) DEFAULT NULL,
- `status` tinyint(1) unsigned DEFAULT NULL,
- `remark` varchar(255) DEFAULT NULL,
- PRIMARY KEY (`id`),
- KEY `pid` (`pid`),
- KEY `status` (`status`)
- ) ENGINE=MyISAM DEFAULT CHARSET=utf8 ;
- CREATE TABLE IF NOT EXISTS `think_role_user` (
- `role_id` mediumint(9) unsigned DEFAULT NULL,
- `user_id` char(32) DEFAULT NULL,
- KEY `group_id` (`role_id`),
- KEY `user_id` (`user_id`)
- ) ENGINE=MyISAM DEFAULT CHARSET=utf8;
2.RBAC类方法
1。authenticate()// 认证方法,检查是否传入用户模型
你需要在配置文件中定义USER_AUTH_MODEL,一般值是User,这个是你的用户表名称,根据实际情况填写。
2。saveAccessList($authId=null)//用于检测用户权限的方法,并保存到Session中
3。getRecordAccessList($authId=null,$module='')// 取得模块的所属记录访问权限列表 返回有权限的记录ID数组
4。checkAccess() //检查当前操作是否需要认证
5。checkLogin()// 登录检查这个是很重要的方法,我们会用了检测用户是否登录
6。AccessDecision($appName=APP_NAME)//权限认证的过滤器方法
7。getAccessList($authId)//取得当前认证号的所有权限列表
8.getModuleAccessList($authId,$module)// 读取模块所属的记录访问权限
官方类文件注释比较详细,我也就不再赘述。主要讲解一下实际用法。
上一次我已经说了第一步是建好相关表和配置文件,接下来才是写代码。这里先补充一下,配置文件参数实例:
- 'USER_AUTH_ON' => true, //开启认证
- 'USER_AUTH_TYPE' => 1, //用户认证使用SESSION标记
- 'USER_AUTH_KEY' => 'authId', //设置认证SESSION的标记名称
- 'ADMIN_AUTH_KEY' => 'admin', //管理员用户标记
- 'USER_AUTH_MODEL' => 'User', //验证用户的表模型u_user
- 'AUTH_PWD_ENCODER' => 'md5', //用户认证密码加密方式
- 'USER_AUTH_GATEWAY' => '/Public/login',//默认的认证网关
- 'NOT_AUTH_MODULE' => 'Public,Index', //默认不需要认证的模块'A,B,C'
- 'REQUIRE_AUTH_MODULE' => '', //默认需要认证的模块
- 'NOT_AUTH_ACTION' => '', //默认不需要认证的动作
- 'REQUIRE_AUTH_ACTION' => '', //默认需要认证的动作
- 'GUEST_AUTH_ON' => false, //是否开启游客授权访问
- 'GUEST_AUTH_ID' => 0, //游客标记
- 'RBAC_ROLE_TABLE' => 'tao_role', //角色表
- 'RBAC_USER_TABLE' => 'tao_role_user', //角色分配表
- 'RBAC_ACCESS_TABLE' => 'tao_access', //权限分配表
- 'RBAC_NODE_TABLE' => 'tao_node', //节点表
你在conf文件夹下的config.php中需写入以上配置参数。
接下来我讲解一下,RBAC的验证流程,首先用户访问某个页面,程序判断是否为公开,不是则跳转到登录页面。登录成功,判断是否有权限访问,没有提示权限错误信息。同样点击某项操作或者模块也是检测是否有权限。结合上面那个类,第一步其实我们是判断访问的操作或者模块是在公开访问的模块组,或者说在不需要验证的模块组,即判断C('NOT_AUTH_MODULE')中有没有该模块,有则为公开组不需要登录,反之跳转到登录页面。登录页面执行checkLogin方法,验证通过跳转到默认首页。在用户操作链接时触发AccessDecision方法,其实这个方法内部调用了检查权限的checkAccess方法,有权限继续操作,没有提示错误。(注:这里其实是先判断了当前用户属于哪个用户组,然后判断用户组具有哪些权限)
3.实例
登录验证部分实例
上一讲我已经说了RBAC的流程,这次通过实际代码来分析。首先讲登录部分,登录无非就是验证用户名密码以及验证码是否正确,我们可以新建一个CommonAction的公共类,用来校验权限,其他所有类继承此类。该类内部写一个初始化方法,用于验证,这一讲先不详细讲解。继续说登录,由于登录是公开模块的方法,所以可以新建一个PublicAction类,用于公共的免验证方法,同时在配置文件中添加
- 'NOT_AUTH_MODULE' => 'Public', //默认不需要认证的模块
- 'USER_AUTH_GATEWAY' => '/Public/login',//默认的认证网关
然后开始编写Public类,具体代码如下:
- <?php
- class PublicAction extends CommonAction{
- //验证码显示
- public function verify(){
- import("ORG.Util.Image");
- Image::buildImageVerify(4,1,"png",100,28,"verify");
- }
- //验证是否账号密码
- function checklogin(){
- //此处多余可自行改为Model自动验证
- if(empty($_POST['username'])) {
- $this->error('帐号错误!');
- }elseif (empty($_POST['password'])){
- $this->error('密码必须!');
- }elseif (empty($_POST['verify'])){
- $this->error('验证码必须!');
- }
- $map=array();
- $map['username']=$_POST['username'];
- $map['status']=array('gt',0);
- if($_SESSION['verify'] != md5($_POST['verify'])) {
- $this->error('验证码错误!');
- }
- import('ORG.Util.RBAC');
- //C('USER_AUTH_MODEL','User');
- //验证账号密码
- $authInfo=RBAC::authenticate($map);
- if(empty($authInfo)){
- $this->error('账号不存在或者被禁用!');
- }else{
- if($authInfo['password']!=md5($_POST['password'])){
- $this->error('账号密码错误!');
- }else{
- $_SESSION[C('USER_AUTH_KEY')]=$authInfo['id'];//记录认证标记,必须有。其他信息根据情况取用。
- $_SESSION['email']=$authInfo['email'];
- $_SESSION['nickname']=$authInfo['nickname'];
- $_SESSION['user']=$authInfo['username'];
- $_SESSION['last_login_date']=$authInfo['last_login_date'];
- $_SESSION['last_login_ip']=$authInfo['last_login_ip'];
- //判断是否为超级管理员
- if($authInfo['username']=='admin'){
- $_SESSION[C('ADMIN_AUTH_KEY')]=true;
- }
- //以下操作为记录本次登录信息
- $user=M('User');
- $lastdate=date('Y-m-d H:i:s');
- $data=array();
- $data['id']=$authInfo['id'];
- $data['last_login_date']=$lastdate;
- $data['last_login_ip']=$_SERVER["REMOTE_ADDR"];
- $user->save($data);
- RBAC::saveAccessList();//用于检测用户权限的方法,并保存到Session中
- $this->assign('jumpUrl',.'/Index/index');
- $this->success('登录成功!');
- }
- }
- }
- //退出登录操作
- function logout(){
- if(!empty($_SESSION[C('USER_AUTH_KEY')])){
- unset($_SESSION[C('USER_AUTH_KEY')]);
- $_SESSION=array();
- session_destroy();
- $this->assign('jumpUrl',/Code.'/login');
- $this->success('登出成功');
- }else{
- $this->error('已经登出了');
- }
- }
- }
以上代码仅实现功能,没有做优化,有些验证的操作可以放到model,session也不用一 一赋值,用数组即可,我想已经入门的应该可以自己改的更好
4.
权限校验部分
新建CommonAction类文件,写入以下代码
- <?php
- class CommonAction extends Action{
- //初始化方法,调用方法时会先执行
- function _initialize(){
- header('Content-Type:text/html;charset=utf-8');
- import('ORG.Util.Cookie');
- // 用户权限检查
- if (C('USER_AUTH_ON') && !in_array(MODULE_NAME, explode(',', C('NOT_AUTH_MODULE')))) {
- import('ORG.Util.RBAC');
- if (!RBAC::AccessDecision()) {
- //检查认证识别号
- if (!$_SESSION [C('USER_AUTH_KEY')]) {
- //跳转到认证网关
- redirect(PHP_FILE . C('USER_AUTH_GATEWAY'));
- }else{
- echo L('_VALID_ACCESS_');
- exit();
- }
- // 没有权限 抛出错误
- if (C('RBAC_ERROR_PAGE')) {
- // 定义权限错误页面
- redirect(C('RBAC_ERROR_PAGE'));
- } else {
- if (C('GUEST_AUTH_ON')) {
- $this->assign('jumpUrl', PHP_FILE . C('USER_AUTH_GATEWAY'));
- }
- // 提示错误信息
- $this->error(L('_VALID_ACCESS_'));
- }
- }
- }
- }
RBAC类使用的更多相关文章
- RBAC类的方法
rbac类的 方法 authenticate($map,$model='')方法 传入查询用户的条件和用户表的MODEL 返回数组包含用户的信息 saveAccessList($authId=null ...
- RBAC类在ThinkPHP中的四种使用方法
第一类:放在登陆控制器的登陆操作中 1.RBAC::authenticate(); 用于在用户表中查找表单提交的用户名的数据,实质上就是一条用户表查寻语句,=====> return M(mod ...
- django RBAC类
# -*- coding: utf-8 -*- ''' @author: Swain @contact: 624420781@qq.com @file: middlewares.py @time: 2 ...
- ThinkPHP 3.2.3 简单后台模块开发(二)RBAC
RBAC(Role-Based Access Controll)基于角色的访问控制 在 ThinkPHP3.2.3 中 RBAC 类位于 /ThinkPHP/Library/Org/Util/Rbac ...
- php_ThinkPHP的RBAC(基于角色权限控制)详解
一.什么是RBAC 基于角色的访问控制(Role-Based Access Control)作为传统访问控制(自主访问,强制访问)的有前景的代替受到广泛的关注. 在RBAC中,权限与角色相关联,用户通 ...
- ThinkPHP的Rbac权限控制
RBAC(Role-Based Access Controll)基于角色的访问控制 在 ThinkPHP3.2.3 中 RBAC 类位于 /ThinkPHP/Library/Org/Util/Rbac ...
- ThinkPHP中RBAC权限带菜单栏显示和详细权限操作
RBAC是什么,能解决什么难题? RBAC是Role-Based Access Control的首字母,译成中文即基于角色的权限访问控制,说白了也就是用户通过角色与权限进行关联[其架构灵感来源于操作系 ...
- [PHP]基于角色的访问控制RBAC
---------------------------------------------------------------------------------------------------- ...
- RBAC相关的配置
一.什么是RBAC 基于角色的访问控制(Role-Based Access Control)作为传统访问控制(自主访问,强制访问)的有前景的代替受到广泛的关注. 在RBAC中,权限与角色相关联,用户通 ...
随机推荐
- 简单的canvas时钟
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8&quo ...
- 获取Echarts的DataZoom的起始值
创建DataZoom拖动事件 myChart.on(ecConfig.EVENT.DATA_ZOOM, eConsole); //事件名, 相关联的方法名 var ecConfig = requi ...
- asp.net 获取汉字字符串的拼音首字母,含多音字
需求:在很多时候数据查询的时候,我们希望输入某个人姓名的拼音首字母进行查询,例如“潘长江”,输入“pcj”,就能搜索潘长江相关信息. 实现: #region 获取汉字转换拼音 首字母 public s ...
- Mac 使用技巧
1.快捷键(Mac 键盘快捷键https://support.apple.com/zh-cn/HT201236) Command-Shift-Z:重做,也就是撤销(Command-Z)的逆向操作 Co ...
- 转-阿里云CentOS Linux服务器上用postfix搭建邮件服务器
http://www.cnblogs.com/dudu/archive/2012/12/12/linux-postfix-mailserver.html 注:本文的邮件服务器只用于发送邮件,也就是ST ...
- python学习--字符串
python的字符串类型为str 定义字符串可以用 ‘abc' , "abc", '''abc''' 查看str的帮助 在python提示符里 help(str) python基于 ...
- js判断中文
var reg = /^[\u4E00-\u9FA5]+$/;if(!reg.test(keywordscn)){ alert('请填写中文') return false;}
- Spring IOC/DI- 3 different types
理论: IOC(Inversion of Control控制反转) DI(依赖注入) (Dependency Injection) 它不是一种技术而是一种思想.当初IOC理论的提出就是为了解决对象 ...
- RDLC开发笔记
1.当报表中使用FormatPercent求百分数时,若分母有小数,务必使用CDbl将其转为double类型,否则会报“错误号”.
- Redis ConnectionException
JAVA 远程链接Redis服务失败,错误信息如下: redis.clients.jedis.exceptions.JedisConnectionException: Could not get a ...