thinkphp5 RBAC類庫

瀏覽:339 發布日期:2019/05/31 分類:用法示例 關鍵字: thinkphp5 RBAC thinkphp3.2
thinkphp5 RBAC類庫(基于thinkphp3.2.3官方類庫修改)
<?php
// +----------------------------------------------------------------------
// | ThinkPHP5 [ WE CAN O IT JUST THINK IT ]
// +----------------------------------------------------------------------
// +----------------------------------------------------------------------
// +----------------------------------------------------------------------
// | Author: gongxulie,<email:[email protected]>
// +----------------------------------------------------------------------
namespace rbac;

use think\Db;
use think\Config;
use think\Session;
use think\Request;

/**
* +------------------------------------------------------------------------------
* 基于角色的數據庫方式驗證類
* +------------------------------------------------------------------------------
*/
// 配置文件增加設置
// USER_AUTH_ON 是否需要認證
// USER_AUTH_TYPE 認證類型
// USER_AUTH_KEY 認證識別號
// REQUIRE_AUTH_MODULE 需要認證???br /> // NOT_AUTH_MODULE 無需認證???br /> // 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,
`status` tinyint(1) 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 = Config::get('USER_AUTH_MODEL');
//使用給定的Map進行認證
return model($model)->where($map)->find();
}

//用于檢測用戶權限的方法,并保存到Session中
static function saveAccessList($authId = null)
{
if (null === $authId) $authId = Session::get(Config::get('USER_AUTH_KEY'));
// 如果使用普通權限模式,保存當前用戶的訪問權限列表
// 對管理員開發所有權限
if (Config::get('USER_AUTH_TYPE') != 2 && !Session::get(Config::get('ADMIN_AUTH_KEY')))
Session::set('_ACCESS_LIST', self::getAccessList($authId));
return;
}

// 取得??櫚乃艏鍬擠夢嗜ㄏ蘗斜?返回有權限的記錄ID數組
static function getRecordAccessList($authId = null, $module = '')
{
if (null === $authId) $authId = Session::get(Config::get('USER_AUTH_KEY'));
if (empty($module)) $module = Request::instance()->controller();
//獲取權限訪問列表
$accessList = self::getModuleAccessList($authId, $module);
return $accessList;
}

//檢查當前操作是否需要認證
static function checkAccess()
{
//如果項目要求認證,并且當前??樾枰現?,則進行權限認證
if (Config::get('USER_AUTH_ON')) {
$_module = array();
$_action = array();
if ("" != Config::get('REQUIRE_AUTH_MODULE')) {
//需要認證的???br /> $_module['yes'] = explode(',', strtoupper(Config::get('REQUIRE_AUTH_MODULE')));
} else {
//無需認證的???br /> $_module['no'] = explode(',', strtoupper(Config::get('NOT_AUTH_MODULE')));
}
$controller_name = Request::instance()->controller();
$action_name = Request::instance()->action();
//檢查當前??槭欠裥枰現?br /> if ((!empty($_module['no']) && !in_array(strtoupper($controller_name), $_module['no'])) || (!empty($_module['yes']) && in_array(strtoupper($controller_name), $_module['yes']))) {
if ("" != Config::get('REQUIRE_AUTH_ACTION')) {
//需要認證的操作
$_action['yes'] = explode(',', strtoupper(Config::get('REQUIRE_AUTH_ACTION')));
} else {
//無需認證的操作
$_action['no'] = explode(',', strtoupper(Config::get('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 (self::checkAccess()) {
//檢查認證識別號
if (!Session::get(Config::get('USER_AUTH_KEY'))) {
if (Config::get('GUEST_AUTH_ON')) {
// 開啟游客授權訪問
$access_list = Session::get('_ACCESS_LIST');
if (!isset($access_list))
// 保存游客權限
self::saveAccessList(Config::get('GUEST_AUTH_ID'));
} else {
// 禁止游客訪問跳轉到認證網關
redirect(Config::get('USER_AUTH_GATEWAY'));
}
}
}
return true;
}

//權限認證的過濾器方法
static public function AccessDecision($appName = '')
{
if (empty($appName)) {
$appName = Request::instance()->module();
}
$controller_name = Request::instance()->controller();
$action_name = Request::instance()->action();
//檢查是否需要認證
if (self::checkAccess()) {
//存在認證識別號,則進行進一步的訪問決策
$accessGuid = md5($appName . $controller_name . $action_name);
$admin_auth_key = Session::get(Config::get('ADMIN_AUTH_KEY'));
if (empty($admin_auth_key)) {
if (Config::get('USER_AUTH_TYPE') == 2) {
//加強驗證和即時驗證模式 更加安全 后臺權限修改可以即時生效
//通過數據庫進行訪問檢查
$accessList = self::getAccessList(Session::get(Config::get('USER_AUTH_KEY')));
} else {
// 如果是管理員或者當前操作已經認證過,無需再次認證
if (Session::get($accessGuid)) {
return true;
}
//登錄驗證模式,比較登錄后保存的權限訪問列表
$accessList = Session::get('_ACCESS_LIST');
}
//判斷是否為組件化模式,如果是,驗證其全??槊?br /> if (!isset($accessList[strtoupper($appName)][strtoupper($controller_name)][strtoupper($action_name)])) {
Session::set($accessGuid, false);
return false;
} else {
Session::set($accessGuid, true);
}
} else {
//管理員無需認證
return true;
}
}
return true;
}

/**
* +----------------------------------------------------------
* 取得當前認證號的所有權限列表
* +----------------------------------------------------------
* @param integer $authId 用戶ID
* +----------------------------------------------------------
* @access public
* +----------------------------------------------------------
*/
static public function getAccessList($authId)
{
// Db方式權限數據
$db = Db::connect(Config::get('RBAC_DB_DSN'));
$table = array('role' => Config::get('RBAC_ROLE_TABLE'), 'user' => Config::get('RBAC_USER_TABLE'), 'access' => Config::get('RBAC_ACCESS_TABLE'), 'node' => Config::get('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'];
// 讀取項目的??槿ㄏ?br /> $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);
// 判斷是否存在公共??櫚娜ㄏ?br /> $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;
}
}
// 依次讀取??櫚牟僮魅ㄏ?br /> 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'];
}
// 和公共??櫚牟僮魅ㄏ蘚喜?br /> $action += $publicAction;
$access[strtoupper($appName)][strtoupper($moduleName)] = array_change_key_case($action, CASE_UPPER);
}
}
return $access;
}

// 讀取??樗艫募鍬擠夢嗜ㄏ?br /> static public function getModuleAccessList($authId, $module)
{
// Db方式
$db = Db::connect(Config::get('RBAC_DB_DSN'));
$table = array('role' => Config::get('RBAC_ROLE_TABLE'), 'user' => Config::get('RBAC_USER_TABLE'), 'access' => Config::get('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";
// dump($sql);die;
$rs = $db->query($sql);
//dump($rs);die;
$access = array();
foreach ($rs as $node) {
$access[] = $node['node_id'];
}
return $access;
}
}
評論( 相關