~~~
<?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 2504 2011-12-28 07:35:29Z liu21st $
/**
+------------------------------------------------------------------------------
* 基于角色的数据库方式验证类
+------------------------------------------------------------------------------
* @category ORG
* @package ORG
* @subpackage Util
* @author liu21st <liu21st@gmail.com>
* @version $Id: RBAC.class.php 2504 2011-12-28 07:35:29Z liu21st $
+------------------------------------------------------------------------------
*/
// 配置文件增加设置
// ADMIN_AUTH_KEY 管理员认证SESSION标记
// USER_AUTH_KEY 用户认证SESSION标记
//
// $_SESSION[C('USER_AUTH_KEY')] 用来保存登陆成功后的用户ID
// $_SESSION[C('ADMIN_AUTH_KEY')] 用来保存登陆成功后的管理员ID
//
// USER_AUTH_ON 是否需要认证
// USER_AUTH_TYPE 认证类型,1是登陆认证,2是实时认证
// USER_AUTH_MODEL 用户模型名称
// GUEST_AUTH_ON 是否开启游客授权访问
// GUEST_AUTH_ID 游客的用户ID
//
// REQUIRE_AUTH_MODULE 需要认证模块(若定义了,则只验证给出的模块;否则验证所有模块)
// NOT_AUTH_MODULE 无需认证模块(若定义了“需要认证模块”则本条定义无效)
// REQUIRE_AUTH_ACTION 需要认证操作(若定义了,则只验证给出的操作;否则验证所有操作)
// NOT_AUTH_ACTION 无需认证操作(若定义了“需要认证操作”则本条定义无效)
//
// USER_AUTH_GATEWAY 认证网关,如果用户没有登录则转到这页(URL路由规则)
// 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 {
// 认证方法
// 得到需要鉴别的用户列表
// 即按照map中给的条件查询用户表(由USER_AUTH_MODEL给出)
static public function authenticate($map,$model='')
{
if(empty($model)) $model = C('USER_AUTH_MODEL');
//使用给定的Map进行认证
return M($model)->where($map)->find();
}
// 用于检测用户权限的方法,并保存到Session中
// 将当前操作用户拥有的所有权限保存到$_SESSION['_ACCESS_LIST']里
// 开销巨大,是对getAccessList的封装
static function saveAccessList($authId=null)
{
if(null===$authId) $authId = $_SESSION[C('USER_AUTH_KEY')];
// 如果使用普通权限模式,保存当前用户的访问权限列表
// 对管理员开放所有权限
// 如果是实时认证(USER_AUTH_TYPE==2),则每次Decision的时候都刷新ACCESS_LIST,
// 就不用在这刷新了
if(C('USER_AUTH_TYPE') !=2 && !$_SESSION[C('ADMIN_AUTH_KEY')] )
$_SESSION['_ACCESS_LIST'] = RBAC::getAccessList($authId);
return ;
}
// 取得模块的所属记录访问权限列表 返回有权限的记录ID数组
// 返回当前模块中当前用户所拥有的权限列表
// 开销巨大,是对getModuleAccessList的封装
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;
}
//检查当前操作是否需要认证,需要则返回true,不需要则返回false
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;
}
// 权限认证的过滤器方法
// 检查当前操作是否被允许,返回bool值
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) {
//实时认证模式,刷新ACCESS_LIST
//加强验证和即时验证模式 更加安全 后台权限修改可以即时生效
//通过数据库进行访问检查
$accessList = RBAC::getAccessList($_SESSION[C('USER_AUTH_KEY')]);
}else {
//登录验证模式,使用登录后填充的ACCESS_LIST
// 如果是管理员或者当前操作已经认证过,无需再次认证
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;
}
/**
+----------------------------------------------------------
* 读取指定模块、指定用户拥有的所有权限列表
+----------------------------------------------------------
* @param integer $authId 用户ID
* @param string $module 模块名
+----------------------------------------------------------
* @access public
+----------------------------------------------------------
*/// 读取指定模块、指定用户拥有的所有权限列表
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;
}
}
~~~
- 前端工程师
- HTML
- 使用meta实现页面的定时刷新或跳转
- 表单相关
- 表单元素input、按钮、文字完美垂直居中对齐方法
- CSS
- 相关工具网站
- JS
- jQuery
- 第1章 初始jQuery
- 环境搭建
- jQuery对象与DOM对象
- jQuery对象转化成DOM对象
- DOM对象转化成jQuery对象
- 第2章 jQuery选择器
- id选择器
- 类选择器
- 元素选择器
- 全选择器(*选择器)
- 层级选择器
- 基本筛选选择器
- 内容筛选选择器
- 可见性筛选选择器
- 属性筛选选择器
- 子元素筛选选择器
- 表单元素选择器
- 表单对象属性筛选选择器
- 特殊选择器this
- 第3章 jQuery的属性与样式
- 元素的数据存储
- 问题解决方案
- 解决innerHTML包含的js代码不能被执行的问题
- webpackdoc
- 前端开发框架
- Bootstrap 3.3.6
- 起步
- 全局 CSS 样式
- 概览
- 栅格系统
- PHP
- PHP入门篇
- 基础总结
- PHP环境变量$_SERVER和系统常量详细说明
- PHP进阶篇
- 数组
- 函数
- 类
- 字符串操作
- 正则表达式
- 会话控制
- 文件系统
- 日期和时间
- 图形图像操作
- PHP异常处理
- 数据库操作
- WEB在线文件管理器
- PHP文件操作
- 获取首层目录信息
- 获取文件信息
- 列表显示文件及大小
- PHP与MySQL关系大揭秘
- PHP支持哪些数据库
- 数据库扩展
- 连接MySQL数据库
- 执行MySQL查询
- 插入新数据到MySQL中
- MVC架构模式分析与设计
- Smarty模版语法
- Smarty的基本语法
- Smarty的条件判断语句
- Smarty的循环语句
- Smarty的文件引用
- Smarty类和对象赋值与使用
- Smarty函数的使用
- functions函数插件的定义和使用
- modifiers变量调节器插件的定义和使用
- block functions区块函数插件的定义和使用
- Smarty实例
- MVC微型框架的建立
- 网络摘抄
- PHPExcel如何读取超大excel文件
- Composer
- Composer技巧
- PHP 开发者该知道的 5 个 Composer 小技巧
- composer常用命令
- Composer使用方法整理(Cy23)
- 利用Composer一步一步搭建自己的PHP框架
- ThinkPHP
- ThinkPHP中RBAC类详解(一)
- 附:添加注释版RBAC类源码
- 常见问题
- 常见方法
- thinkphp 合并两个字段组合成一个临时字段concat函数
- ThinkPHP Where 条件中使用表达式
- 编程相关工具
- Eclipse
- Eclipse或Zendstudio汉化
- Zend studio
- Zendstudio快捷键
- Zend Studio实用快捷键一览表
- Sublime text
- Sublime text快捷键
- 16 个 Sublime Text 快捷键
- Emmet的用法及相关语法
- VS Code
- 数据库
- MySql
- 问题汇总
- mysql创建存储过程失败1307错误解决
- Mysql出现Field * doesn't have a default value解决办法
- mysql:ADO连接mysql数据库,驱动程序和ODBC数据源问题
- 自己如何正确获取MYSQL的ADO连接字符串
- 网上摘抄
- mysql 存在更新 不存在插入
- Mysql字符串字段中是否包含某个字符串,用 find_in_set
- mysql字段类型对应的数字编号
- 5.7mysql group分组查询错误问题
- mysql常用操作语句
- SQL2005
- SQL常见错误
- 使用 sp_change_users_login 修复产生的孤 立账户 & 还原中的孤立用户
- ASP
- Url编码解码函数合集 含utf-8和gb2312
- 其他前端相关技巧
- 联机查看 Office 文档
- 服务器配置
- windows
- 服务器安装
- XAMPP自带TOMCAT插件可以支持php+java
- IIS
- iis7服务器,客户端无法下载exe文件的解决之道
- Linux
- ubuntu
- Linux安装JDK
- 辅助开发工具
- Git