THINKPHP中RBAC代码备注

来源:互联网 发布:淡斑眼霜 知乎 编辑:程序博客网 时间:2024/06/05 22:41
// +----------------------------------------------------------------------// | ThinkPHP [ WE CAN DO IT JUST THINK IT ]// +----------------------------------------------------------------------// | Copyright (c) 2009 http://thinkphp.cn All rights reserved.// +----------------------------------------------------------------------// | Licensed ( http://www.apache.org/licenses/LICENSE-2.0 )// +----------------------------------------------------------------------// | Author: liu21st <liu21st@gmail.com>// +----------------------------------------------------------------------// $Id: RBAC.class.php 2601 2012-01-15 04:59:14Z liu21st $/** +------------------------------------------------------------------------------ * 基于角色的数据库方式验证类 +------------------------------------------------------------------------------ * @category   ORG * @package  ORG * @subpackage  Util * @author    liu21st <liu21st@gmail.com> * @version   $Id: RBAC.class.php 2601 2012-01-15 04:59:14Z liu21st $ +------------------------------------------------------------------------------ */// 配置文件增加设置// USER_AUTH_ON 是否需要认证// USER_AUTH_TYPE 认证类型// 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 COMMENT 'role表用户组ID',  `node_id` smallint(6) unsigned NOT NULL COMMENT 'node表节点ID',  `level` tinyint(1) NOT NULL COMMENT 'node表level等级',  `pid` smallint(6) NOT NULL 'node表父ID',  `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 COMMENT '项目模块方法名',  `title` varchar(50) DEFAULT NULL COMMENT '节点名称',  `status` tinyint(1) DEFAULT '0' COMMENT '状态',  `remark` varchar(255) DEFAULT NULL COMMENT '备注',  `sort` smallint(6) unsigned DEFAULT NULL COMMENT '排序',  `pid` smallint(6) unsigned NOT NULL COMMENT '父ID',  `level` tinyint(1) unsigned NOT NULL COMMENT '级别项目1模块2方法3',  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 COMMENT '用户组名称',  `pid` smallint(6) DEFAULT NULL COMMENT '父ID',  `status` tinyint(1) unsigned DEFAULT NULL COMMENT '状态',  `remark` varchar(255) DEFAULT NULL COMMENT '备注',  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 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;*/class RBAC {    // 认证方法    static public function authenticate($map,$model='')    {        if(empty($model)) $model =  C('USER_AUTH_MODEL');        //使用给定的Map进行认证        return M($model)->where($map)->find();    }    //用于检测用户权限的方法,并保存到Session中    static function saveAccessList($authId=null)    {        if(null===$authId)   $authId = $_SESSION[C('USER_AUTH_KEY')];        // 如果使用普通权限模式,保存当前用户的访问权限列表        // 对管理员开发所有权限        if(C('USER_AUTH_TYPE') !=2 && !$_SESSION[C('ADMIN_AUTH_KEY')] )            $_SESSION['_ACCESS_LIST']=RBAC::getAccessList($authId);        return ;    }// 取得模块的所属记录访问权限列表 返回有权限的记录ID数组static function getRecordAccessList($authId=null,$module='') {        if(null===$authId)   $authId = $_SESSION[C('USER_AUTH_KEY')];        if(empty($module))  $module=MODULE_NAME;        //获取权限访问列表        $accessList = RBAC::getModuleAccessList($authId,$module);        return $accessList;}    //检查当前操作是否需要认证    static function checkAccess()    {        //如果项目要求认证,并且当前模块需要认证,则进行权限认证        if( C('USER_AUTH_ON') ){$_module=array();$_action=array();            if("" != C('REQUIRE_AUTH_MODULE')) {                //需要认证的模块                $_module['yes'] = explode(',',strtoupper(C('REQUIRE_AUTH_MODULE')));            }else {                //无需认证的模块                $_module['no'] = explode(',',strtoupper(C('NOT_AUTH_MODULE')));            }            //检查当前模块是否需要认证            if((!empty($_module['no']) && !in_array(strtoupper(MODULE_NAME),$_module['no'])) || (!empty($_module['yes']) && in_array(strtoupper(MODULE_NAME),$_module['yes']))) {if("" != C('REQUIRE_AUTH_ACTION')) {//需要认证的操作$_action['yes'] = explode(',',strtoupper(C('REQUIRE_AUTH_ACTION')));}else {//无需认证的操作$_action['no'] = explode(',',strtoupper(C('NOT_AUTH_ACTION')));}//检查当前操作是否需要认证if((!empty($_action['no']) && !in_array(strtoupper(ACTION_NAME),$_action['no'])) || (!empty($_action['yes']) && in_array(strtoupper(ACTION_NAME),$_action['yes']))) {return true;}else {return false;}            }else {                return false;            }        }        return false;    }// 登录检查static public function checkLogin() {        //检查当前操作是否需要认证        if(RBAC::checkAccess()) {            //检查认证识别号            if(!$_SESSION[C('USER_AUTH_KEY')]) {                if(C('GUEST_AUTH_ON')) {                    // 开启游客授权访问                    if(!isset($_SESSION['_ACCESS_LIST']))                        // 保存游客权限                        RBAC::saveAccessList(C('GUEST_AUTH_ID'));                }else{                    // 禁止游客访问跳转到认证网关                    redirect(PHP_FILE.C('USER_AUTH_GATEWAY'));                }            }        }        return true;}    //权限认证的过滤器方法    static public function AccessDecision($appName=APP_NAME)    {        //检查是否需要认证        if(RBAC::checkAccess()) {            //存在认证识别号,则进行进一步的访问决策            $accessGuid   =   md5($appName.MODULE_NAME.ACTION_NAME);            if(empty($_SESSION[C('ADMIN_AUTH_KEY')])) {                if(C('USER_AUTH_TYPE')==2) {                    //加强验证和即时验证模式 更加安全 后台权限修改可以即时生效                    //通过数据库进行访问检查                    $accessList = RBAC::getAccessList($_SESSION[C('USER_AUTH_KEY')]);                }else {                    // 如果是管理员或者当前操作已经认证过,无需再次认证                    if( $_SESSION[$accessGuid]) {                        return true;                    }                    //登录验证模式,比较登录后保存的权限访问列表                    $accessList = $_SESSION['_ACCESS_LIST'];                }                //判断是否为组件化模式,如果是,验证其全模块名                $module = defined('P_MODULE_NAME')?  P_MODULE_NAME   :   MODULE_NAME;                if(!isset($accessList[strtoupper($appName)][strtoupper($module)][strtoupper(ACTION_NAME)])) {                    $_SESSION[$accessGuid]  =   false;                    return false;                }                else {                    $_SESSION[$accessGuid]=true;                }            }else{                //管理员无需认证return true;}        }        return true;    }    /**     +----------------------------------------------------------     * 取得当前认证号的所有权限列表     +----------------------------------------------------------     * @param integer $authId 用户ID     +----------------------------------------------------------     * @access public     +----------------------------------------------------------     */    static public function getAccessList($authId)    {        // Db方式权限数据        $db     =   Db::getInstance(C('RBAC_DB_DSN'));        $table = array('role'=>C('RBAC_ROLE_TABLE'),'user'=>C('RBAC_USER_TABLE'),'access'=>C('RBAC_ACCESS_TABLE'),'node'=>C('RBAC_NODE_TABLE'));        $sql    =   "select node.id,node.name from ".                    $table['role']." as role,".                    $table['user']." as user,".                    $table['access']." as access ,".                    $table['node']." as node ".                    "where user.user_id='{$authId}' and user.role_id=role.id and ( access.role_id=role.id  or (access.role_id=role.pid and role.pid!=0 ) ) and role.status=1 and access.node_id=node.id and node.level=1 and node.status=1";        $apps =   $db->query($sql);        $access =  array();        foreach($apps as $key=>$app) {            $appId=$app['id'];            $appName = $app['name'];            // 读取项目的模块权限            $access[strtoupper($appName)]   =  array();            $sql    =   "select node.id,node.name from ".                    $table['role']." as role,".                    $table['user']." as user,".                    $table['access']." as access ,".                    $table['node']." as node ".                    "where user.user_id='{$authId}' and user.role_id=role.id and ( access.role_id=role.id  or (access.role_id=role.pid and role.pid!=0 ) ) and role.status=1 and access.node_id=node.id and node.level=2 and node.pid={$appId} and node.status=1";            $modules =   $db->query($sql);            // 判断是否存在公共模块的权限            $publicAction  = array();            foreach($modules as $key=>$module) {                $moduleId = $module['id'];                $moduleName = $module['name'];                if('PUBLIC'== strtoupper($moduleName)) {                $sql    =   "select node.id,node.name from ".                    $table['role']." as role,".                    $table['user']." as user,".                    $table['access']." as access ,".                    $table['node']." as node ".                    "where user.user_id='{$authId}' and user.role_id=role.id and ( access.role_id=role.id  or (access.role_id=role.pid and role.pid!=0 ) ) and role.status=1 and access.node_id=node.id and node.level=3 and node.pid={$moduleId} and node.status=1";                    $rs =   $db->query($sql);                    foreach ($rs as $a){                        $publicAction[$a['name']] = $a['id'];                    }                    unset($modules[$key]);                    break;                }            }            // 依次读取模块的操作权限            foreach($modules as $key=>$module) {                $moduleId = $module['id'];                $moduleName = $module['name'];                $sql    =   "select node.id,node.name from ".                    $table['role']." as role,".                    $table['user']." as user,".                    $table['access']." as access ,".                    $table['node']." as node ".                    "where user.user_id='{$authId}' and user.role_id=role.id and ( access.role_id=role.id  or (access.role_id=role.pid and role.pid!=0 ) ) and role.status=1 and access.node_id=node.id and node.level=3 and node.pid={$moduleId} and node.status=1";                $rs =   $db->query($sql);                $action = array();                foreach ($rs as $a){                    $action[$a['name']] = $a['id'];                }                // 和公共模块的操作权限合并                $action += $publicAction;                $access[strtoupper($appName)][strtoupper($moduleName)]   =  array_change_key_case($action,CASE_UPPER);            }        }        return $access;    }// 读取模块所属的记录访问权限static public function getModuleAccessList($authId,$module) {        // Db方式        $db     =   Db::getInstance(C('RBAC_DB_DSN'));        $table = array('role'=>C('RBAC_ROLE_TABLE'),'user'=>C('RBAC_USER_TABLE'),'access'=>C('RBAC_ACCESS_TABLE'));        $sql    =   "select access.node_id from ".                    $table['role']." as role,".                    $table['user']." as user,".                    $table['access']." as access ".                    "where user.user_id='{$authId}' and user.role_id=role.id and ( access.role_id=role.id  or (access.role_id=role.pid and role.pid!=0 ) ) and role.status=1 and  access.module='{$module}' and access.status=1";        $rs =   $db->query($sql);        $access=array();        foreach ($rs as $node){            $access[]=$node['node_id'];        }return $access;}}

原创粉丝点击