219513lpc

RBAC类使用


1.实现
首先我们先简单理解一下RBAC,顾名思义,RBAC是基于角色的权限设计。既然根据角色去分权限,那么我们就得有角色表,权限表,角色对应权限表,这是最基本的。角色是什么,就是你的身份,你的职位,也就是一个用户拥有这个身份才能获得某种权力。插一句,角色下辖的是用户,一个角色组可以有多个用户,一个用户也可能有多个角色,多对多的关系。
打开RBAC.class.php,你会发现官方已经告诉你,需要准备的东西。首先是配置文件需要设置的东西如下:

  1. // 配置文件增加设置
  2.  // USER_AUTH_ON 是否需要认证
  3.  // USER_AUTH_TYPE 认证类型 1 登录认证 2 实时认证
  4.  // USER_AUTH_KEY 认证识别号
  5.  // REQUIRE_AUTH_MODULE  需要认证模块
  6.  // NOT_AUTH_MODULE 无需认证模块
  7.  // USER_AUTH_GATEWAY 认证网关
  8.  // RBAC_DB_DSN  数据库连接DSN
  9.  // RBAC_ROLE_TABLE 角色表名称
  10.  // RBAC_USER_TABLE 用户表名称
  11.  // RBAC_ACCESS_TABLE 权限表名称
  12.  // RBAC_NODE_TABLE 节点表名称
  1. /*
  2. -- --------------------------------------------------------
  3. CREATE TABLE IF NOT EXISTS `think_access` (
  4.   `role_id` smallint(6) unsigned NOT NULL,
  5.   `node_id` smallint(6) unsigned NOT NULL,
  6.   `level` tinyint(1) NOT NULL,
  7.   `module` varchar(50) DEFAULT NULL,
  8.   KEY `groupId` (`role_id`),
  9.   KEY `nodeId` (`node_id`)
  10. ) ENGINE=MyISAM DEFAULT CHARSET=utf8;
  11. CREATE TABLE IF NOT EXISTS `think_node` (
  12.   `id` smallint(6) unsigned NOT NULL AUTO_INCREMENT,
  13.   `name` varchar(20) NOT NULL,
  14.   `title` varchar(50) DEFAULT NULL,
  15.   `status` tinyint(1) DEFAULT '0',
  16.   `remark` varchar(255) DEFAULT NULL,
  17.   `sort` smallint(6) unsigned DEFAULT NULL,
  18.   `pid` smallint(6) unsigned NOT NULL,
  19.   `level` tinyint(1) unsigned NOT NULL,
  20.   PRIMARY KEY (`id`),
  21.   KEY `level` (`level`),
  22.   KEY `pid` (`pid`),
  23.   KEY `status` (`status`),
  24.   KEY `name` (`name`)
  25. ) ENGINE=MyISAM  DEFAULT CHARSET=utf8;
  26. CREATE TABLE IF NOT EXISTS `think_role` (
  27.   `id` smallint(6) unsigned NOT NULL AUTO_INCREMENT,
  28.   `name` varchar(20) NOT NULL,
  29.   `pid` smallint(6) DEFAULT NULL,
  30.   `status` tinyint(1) unsigned DEFAULT NULL,
  31.   `remark` varchar(255) DEFAULT NULL,
  32.   PRIMARY KEY (`id`),
  33.   KEY `pid` (`pid`),
  34.   KEY `status` (`status`)
  35. ) ENGINE=MyISAM  DEFAULT CHARSET=utf8 ;
  36. CREATE TABLE IF NOT EXISTS `think_role_user` (
  37.   `role_id` mediumint(9) unsigned DEFAULT NULL,
  38.   `user_id` char(32) DEFAULT NULL,
  39.   KEY `group_id` (`role_id`),
  40.   KEY `user_id` (`user_id`)
  41. ) 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)// 读取模块所属的记录访问权限
官方类文件注释比较详细,我也就不再赘述。主要讲解一下实际用法。
上一次我已经说了第一步是建好相关表和配置文件,接下来才是写代码。这里先补充一下,配置文件参数实例:

  1.     'USER_AUTH_ON'            =>        true,             //开启认证
  2.     'USER_AUTH_TYPE'        =>        1,              //用户认证使用SESSION标记
  3.     'USER_AUTH_KEY'            =>        'authId',          //设置认证SESSION的标记名称
  4.     'ADMIN_AUTH_KEY'        =>        'admin',        //管理员用户标记
  5.     'USER_AUTH_MODEL'        =>        'User',          //验证用户的表模型u_user
  6.     'AUTH_PWD_ENCODER'        =>        'md5',             //用户认证密码加密方式
  7.     'USER_AUTH_GATEWAY'        =>        '/Public/login',//默认的认证网关
  8.     'NOT_AUTH_MODULE'        =>        'Public,Index',          //默认不需要认证的模块'A,B,C'
  9.     'REQUIRE_AUTH_MODULE'    =>        '',              //默认需要认证的模块
  10.     'NOT_AUTH_ACTION'        =>        '',                //默认不需要认证的动作
  11.     'REQUIRE_AUTH_ACTION'    =>        '',                //默认需要认证的动作
  12.     'GUEST_AUTH_ON'            =>        false,            //是否开启游客授权访问
  13.     'GUEST_AUTH_ID'            =>        0,                 //游客标记    
  14.     'RBAC_ROLE_TABLE'        =>        'tao_role',       //角色表
  15.     'RBAC_USER_TABLE'        =>        'tao_role_user', //角色分配表
  16.     'RBAC_ACCESS_TABLE'        =>        'tao_access',   //权限分配表
  17.     'RBAC_NODE_TABLE'        =>        'tao_node',     //节点表

你在conf文件夹下的config.php中需写入以上配置参数。
接下来我讲解一下,RBAC的验证流程,首先用户访问某个页面,程序判断是否为公开,不是则跳转到登录页面。登录成功,判断是否有权限访问,没有提示权限错误信息。同样点击某项操作或者模块也是检测是否有权限。结合上面那个类,第一步其实我们是判断访问的操作或者模块是在公开访问的模块组,或者说在不需要验证的模块组,即判断C('NOT_AUTH_MODULE')中有没有该模块,有则为公开组不需要登录,反之跳转到登录页面。登录页面执行checkLogin方法,验证通过跳转到默认首页。在用户操作链接时触发AccessDecision方法,其实这个方法内部调用了检查权限的checkAccess方法,有权限继续操作,没有提示错误。(注:这里其实是先判断了当前用户属于哪个用户组,然后判断用户组具有哪些权限)

3.实例

登录验证部分实例
上一讲我已经说了RBAC的流程,这次通过实际代码来分析。首先讲登录部分,登录无非就是验证用户名密码以及验证码是否正确,我们可以新建一个CommonAction的公共类,用来校验权限,其他所有类继承此类。该类内部写一个初始化方法,用于验证,这一讲先不详细讲解。继续说登录,由于登录是公开模块的方法,所以可以新建一个PublicAction类,用于公共的免验证方法,同时在配置文件中添加

  1. 'NOT_AUTH_MODULE'        =>        'Public',          //默认不需要认证的模块
  2.  'USER_AUTH_GATEWAY'        =>        '/Public/login',//默认的认证网关

然后开始编写Public类,具体代码如下:

  1. <?php
  2.  class PublicAction extends CommonAction{
  3.     //验证码显示
  4.     public function verify(){
  5.         import("ORG.Util.Image");
  6.         Image::buildImageVerify(4,1,"png",100,28,"verify");        
  7.     }
  8.     //验证是否账号密码
  9.     function checklogin(){
  10.         //此处多余可自行改为Model自动验证
  11.         if(empty($_POST['username'])) {
  12.             $this->error('帐号错误!');
  13.         }elseif (empty($_POST['password'])){
  14.             $this->error('密码必须!');
  15.         }elseif (empty($_POST['verify'])){
  16.             $this->error('验证码必须!');
  17.         }
  18.         $map=array();
  19.         $map['username']=$_POST['username'];
  20.         $map['status']=array('gt',0);
  21.         if($_SESSION['verify'] != md5($_POST['verify'])) {
  22.             $this->error('验证码错误!');
  23.         }
  24.         
  25.         import('ORG.Util.RBAC');
  26.         //C('USER_AUTH_MODEL','User');
  27.         //验证账号密码
  28.          $authInfo=RBAC::authenticate($map);
  29.         
  30.         if(empty($authInfo)){
  31.             $this->error('账号不存在或者被禁用!');
  32.         }else{
  33.             if($authInfo['password']!=md5($_POST['password'])){
  34.                 $this->error('账号密码错误!');
  35.             }else{
  36.                     
  37.             $_SESSION[C('USER_AUTH_KEY')]=$authInfo['id'];//记录认证标记,必须有。其他信息根据情况取用。
  38.             $_SESSION['email']=$authInfo['email'];
  39.             $_SESSION['nickname']=$authInfo['nickname'];
  40.             $_SESSION['user']=$authInfo['username'];
  41.             $_SESSION['last_login_date']=$authInfo['last_login_date'];
  42.             $_SESSION['last_login_ip']=$authInfo['last_login_ip'];
  43.             //判断是否为超级管理员
  44.             if($authInfo['username']=='admin'){
  45.                 $_SESSION[C('ADMIN_AUTH_KEY')]=true;
  46.             }
  47.            //以下操作为记录本次登录信息
  48.             $user=M('User');
  49.             $lastdate=date('Y-m-d H:i:s');
  50.             $data=array();
  51.             $data['id']=$authInfo['id'];
  52.             $data['last_login_date']=$lastdate;
  53.             $data['last_login_ip']=$_SERVER["REMOTE_ADDR"];
  54.             $user->save($data);
  55.             RBAC::saveAccessList();//用于检测用户权限的方法,并保存到Session中
  56.             $this->assign('jumpUrl',.'/Index/index');
  57.             $this->success('登录成功!');
  58.             }
  59.         }
  60.     }
  61.     //退出登录操作
  62.     function logout(){
  63.         if(!empty($_SESSION[C('USER_AUTH_KEY')])){
  64.             unset($_SESSION[C('USER_AUTH_KEY')]);
  65.             $_SESSION=array();
  66.             session_destroy();
  67.             $this->assign('jumpUrl',/Code.'/login');
  68.             $this->success('登出成功');
  69.         }else{
  70.             $this->error('已经登出了');
  71.         }
  72.     }
  73.     
  74. }

以上代码仅实现功能,没有做优化,有些验证的操作可以放到model,session也不用一 一赋值,用数组即可,我想已经入门的应该可以自己改的更好

4.

权限校验部分
新建CommonAction类文件,写入以下代码

    1. <?php
    2.  class CommonAction extends Action{
    3.  //初始化方法,调用方法时会先执行
    4.  function _initialize(){
    5.     header('Content-Type:text/html;charset=utf-8');
    6.         import('ORG.Util.Cookie');
    7.         // 用户权限检查
    8.         if (C('USER_AUTH_ON') && !in_array(MODULE_NAME, explode(',', C('NOT_AUTH_MODULE')))) {
    9.             import('ORG.Util.RBAC');
    10.             if (!RBAC::AccessDecision()) {
    11.                 //检查认证识别号
    12.                 if (!$_SESSION [C('USER_AUTH_KEY')]) {
    13.                     //跳转到认证网关
    14.                     redirect(PHP_FILE . C('USER_AUTH_GATEWAY'));
    15.                 }else{
    16.                     echo L('_VALID_ACCESS_');
    17.                     exit();
    18.                 }
    19.                 // 没有权限 抛出错误
    20.                 if (C('RBAC_ERROR_PAGE')) {
    21.                     // 定义权限错误页面
    22.                     redirect(C('RBAC_ERROR_PAGE'));
    23.                 } else {
    24.                     if (C('GUEST_AUTH_ON')) {
    25.                         $this->assign('jumpUrl', PHP_FILE . C('USER_AUTH_GATEWAY'));
    26.                     }
    27.                     // 提示错误信息
    28.                     $this->error(L('_VALID_ACCESS_'));
    29.                 }
    30.             }
    31.         }
    32.  }

posted on 2014-04-04 16:59  219513lpc  阅读(333)  评论(0)    收藏  举报

导航