rbac.class.php,thinkphp/Rbac.class.php at master · top-think/thinkphp · GitHub

// +----------------------------------------------------------------------

// | 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

// +----------------------------------------------------------------------

namespace Org\Util;

use Think\Db;

/**

* 基于角色的数据库方式验证类

*/

// 配置文件增加设置

// 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

{

// 认证方法

public static function authenticate($map, $model = '')

{

if (empty($model)) {

$model = C('USER_AUTH_MODEL');

}

//使用给定的Map进行认证

return M($model)->where($map)->find();

}

//用于检测用户权限的方法,并保存到Session中

public 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'] = self::getAccessList($authId);

}

return;

}

// 取得模块的所属记录访问权限列表 返回有权限的记录ID数组

public static function getRecordAccessList($authId = null, $module = '')

{

if (null === $authId) {

$authId = $_SESSION[C('USER_AUTH_KEY')];

}

if (empty($module)) {

$module = CONTROLLER_NAME;

}

//获取权限访问列表

$accessList = self::getModuleAccessList($authId, $module);

return $accessList;

}

//检查当前操作是否需要认证

public 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(CONTROLLER_NAME), $_module['no'])) || (!empty($_module['yes']) && in_array(strtoupper(CONTROLLER_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;

}

// 登录检查

public static function checkLogin()

{

//检查当前操作是否需要认证

if (self::checkAccess()) {

//检查认证识别号

if (!$_SESSION[C('USER_AUTH_KEY')]) {

if (C('GUEST_AUTH_ON')) {

// 开启游客授权访问

if (!isset($_SESSION['_ACCESS_LIST']))

// 保存游客权限

{

self::saveAccessList(C('GUEST_AUTH_ID'));

}

} else {

// 禁止游客访问跳转到认证网关

redirect(PHP_FILE . C('USER_AUTH_GATEWAY'));

}

}

}

return true;

}

//权限认证的过滤器方法

public static function AccessDecision($appName = MODULE_NAME)

{

//检查是否需要认证

if (self::checkAccess()) {

//存在认证识别号,则进行进一步的访问决策

$accessGuid = md5($appName . CONTROLLER_NAME . ACTION_NAME);

if (empty($_SESSION[C('ADMIN_AUTH_KEY')])) {

if (C('USER_AUTH_TYPE') == 2) {

//加强验证和即时验证模式 更加安全 后台权限修改可以即时生效

//通过数据库进行访问检查

$accessList = self::getAccessList($_SESSION[C('USER_AUTH_KEY')]);

} else {

// 如果是管理员或者当前操作已经认证过,无需再次认证

if ($_SESSION[$accessGuid]) {

return true;

}

//登录验证模式,比较登录后保存的权限访问列表

$accessList = $_SESSION['_ACCESS_LIST'];

}

//判断是否为组件化模式,如果是,验证其全模块名

if (!isset($accessList[strtoupper($appName)][strtoupper(CONTROLLER_NAME)][strtoupper(ACTION_NAME)])) {

$_SESSION[$accessGuid] = false;

return false;

} else {

$_SESSION[$accessGuid] = true;

}

} else {

//管理员无需认证

return true;

}

}

return true;

}

/**

* 取得当前认证号的所有权限列表

* @param integer $authId 用户ID

* @access public

*/

public static 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;

}

// 读取模块所属的记录访问权限

public static 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;

}

}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值