/ThinkPHP/Extend/Library/ORG/Util/RBAC.class.php
PHP | 292 lines | 160 code | 8 blank | 124 comment | 30 complexity | 2bda988faf8b7f0bb00817879ab454a8 MD5 | raw file
- <?php
- // +----------------------------------------------------------------------
- // | 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 2947 2012-05-13 15:57:48Z liu21st@gmail.com $
-
- /**
- +------------------------------------------------------------------------------
- * 基于角色的数据库方式验证类
- +------------------------------------------------------------------------------
- * @category ORG
- * @package ORG
- * @subpackage Util
- * @author liu21st <liu21st@gmail.com>
- * @version $Id: RBAC.class.php 2947 2012-05-13 15:57:48Z liu21st@gmail.com $
- +------------------------------------------------------------------------------
- */
- // 配置文件增加设置
- // 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,
- `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;
- */
- 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;
- }
- }