ThinkPHP5权限控制
我在用ThinkPHP5做开发的时候发现,它没有权限类,自己写太麻烦,于是就想到了把TP3里面的权限类拿来修改使用,结果这种方法是可行的,下面记录附上修改后的Auth.php权限类
1 <?php 2 // +---------------------------------------------------------------------- 3 // | ThinkPHP [ WE CAN DO IT JUST THINK IT ] 4 // +---------------------------------------------------------------------- 5 // | Copyright (c) 2011 http://thinkphp.cn All rights reserved. 6 // +---------------------------------------------------------------------- 7 // | Licensed ( http://www.apache.org/licenses/LICENSE-2.0 ) 8 // +---------------------------------------------------------------------- 9 // | Author: luofei614 <weibo.com/luofei614> 10 // +---------------------------------------------------------------------- 11 // 功能:权限类 12 namespace app\admin\controller; 13 /** 14 * 权限认证类 15 * 功能特性: 16 * 1,是对规则进行认证,不是对节点进行认证。用户可以把节点当作规则名称实现对节点进行认证。 17 * $auth=new Auth(); $auth->check('规则名称','用户id') 18 * 2,可以同时对多条规则进行认证,并设置多条规则的关系(or或者and) 19 * $auth=new Auth(); $auth->check('规则1,规则2','用户id','and') 20 * 第三个参数为and时表示,用户需要同时具有规则1和规则2的权限。 当第三个参数为or时,表示用户值需要具备其中一个条件即可。默认为or 21 * 3,一个用户可以属于多个用户组(think_auth_group_access表 定义了用户所属用户组)。我们需要设置每个用户组拥有哪些规则(think_auth_group 定义了用户组权限) 22 * 23 * 4,支持规则表达式。 24 * 在think_auth_rule 表中定义一条规则时,如果type为1, condition字段就可以定义规则表达式。 如定义{score}>5 and {score}<100 表示用户的分数在5-100之间时这条规则才会通过。 25 */ 26 27 //数据库 28 /* 29 -- ---------------------------- 30 -- think_auth_rule,规则表, 31 -- id:主键,name:规则唯一标识, title:规则中文名称 status 状态:为1正常,为0禁用,condition:规则表达式,为空表示存在就验证,不为空表示按照条件验证 32 -- ---------------------------- 33 DROP TABLE IF EXISTS `think_auth_rule`; 34 CREATE TABLE `think_auth_rule` ( 35 `id` mediumint(8) unsigned NOT NULL AUTO_INCREMENT, 36 `name` char(80) NOT NULL DEFAULT '', 37 `title` char(20) NOT NULL DEFAULT '', 38 `type` tinyint(1) NOT NULL DEFAULT '1', 39 `status` tinyint(1) NOT NULL DEFAULT '1', 40 `condition` char(100) NOT NULL DEFAULT '', # 规则附加条件,满足附加条件的规则,才认为是有效的规则 41 PRIMARY KEY (`id`), 42 UNIQUE KEY `name` (`name`) 43 ) ENGINE=MyISAM DEFAULT CHARSET=utf8; 44 -- ---------------------------- 45 -- think_auth_group 用户组表, 46 -- id:主键, title:用户组中文名称, rules:用户组拥有的规则id, 多个规则","隔开,status 状态:为1正常,为0禁用 47 -- ---------------------------- 48 DROP TABLE IF EXISTS `think_auth_group`; 49 CREATE TABLE `think_auth_group` ( 50 `id` mediumint(8) unsigned NOT NULL AUTO_INCREMENT, 51 `title` char(100) NOT NULL DEFAULT '', 52 `status` tinyint(1) NOT NULL DEFAULT '1', 53 `rules` char(80) NOT NULL DEFAULT '', 54 PRIMARY KEY (`id`) 55 ) ENGINE=MyISAM DEFAULT CHARSET=utf8; 56 -- ---------------------------- 57 -- think_auth_group_access 用户组明细表 58 -- uid:用户id,group_id:用户组id 59 -- ---------------------------- 60 DROP TABLE IF EXISTS `think_auth_group_access`; 61 CREATE TABLE `think_auth_group_access` ( 62 `uid` mediumint(8) unsigned NOT NULL, 63 `group_id` mediumint(8) unsigned NOT NULL, 64 UNIQUE KEY `uid_group_id` (`uid`,`group_id`), 65 KEY `uid` (`uid`), 66 KEY `group_id` (`group_id`) 67 ) ENGINE=MyISAM DEFAULT CHARSET=utf8; 68 */ 69 70 class Auth{ 71 72 //默认配置 73 protected $_config = array( 74 'auth_on' => true, // 认证开关 75 'auth_type' => 1, // 认证方式,1为实时认证;2为登录认证。 76 'auth_group' => '__AUTH_GROUP__', // 用户组数据表名 77 'auth_group_access' => 'auth_group_access', // 用户-用户组关系表 78 'auth_rule' => 'auth_rule', // 权限规则表 79 'auth_user' => 'member' // 用户信息表 80 ); 81 82 public function __construct() { 83 $t=config('auth_config'); 84 if (config('auth_config')) { 85 //可设置配置项 auth_config, 此配置项为数组。 86 $this->_config = array_merge($this->_config, config('auth_config')); 87 } 88 } 89 90 /** 91 * 检查权限 92 * @param name string|array 需要验证的规则列表,支持逗号分隔的权限规则或索引数组 93 * @param uid int 认证用户的id 94 * @param string mode 执行check的模式 95 * @param relation string 如果为 'or' 表示满足任一条规则即通过验证;如果为 'and'则表示需满足所有规则才能通过验证 96 * @return boolean 通过验证返回true;失败返回false 97 */ 98 public function check($name, $uid, $type=1, $mode='url', $relation='or') { 99 if (!$this->_config['auth_on']) 100 return true; 101 $authList = $this->getAuthList($uid,$type); //获取用户需要验证的所有有效规则列表 102 if (is_string($name)) { 103 $name = strtolower($name); 104 if (strpos($name, ',') !== false) { 105 $name = explode(',', $name); 106 } else { 107 $name = array($name); 108 } 109 } 110 $list = array(); //保存验证通过的规则名 111 if ($mode=='url') { 112 $REQUEST = unserialize( strtolower(serialize($_REQUEST)) ); 113 } 114 foreach ( $authList as $auth ) { 115 $query = preg_replace('/^.+\?/U','',$auth); 116 if ($mode=='url' && $query!=$auth ) { 117 parse_str($query,$param); //解析规则中的param 118 $intersect = array_intersect_assoc($REQUEST,$param); 119 $auth = preg_replace('/\?.*$/U','',$auth); 120 if ( in_array($auth,$name) && $intersect==$param ) { //如果节点相符且url参数满足 121 $list[] = $auth ; 122 } 123 }else if (in_array($auth , $name)){ 124 $list[] = $auth ; 125 } 126 } 127 if ($relation == 'or' and !empty($list)) { 128 return true; 129 } 130 $diff = array_diff($name, $list); 131 if ($relation == 'and' and empty($diff)) { 132 return true; 133 } 134 return false; 135 } 136 137 /** 138 * 根据用户id获取用户组,返回值为数组 139 * @param uid int 用户id 140 * @return array 用户所属的用户组 array( 141 * array('uid'=>'用户id','group_id'=>'用户组id','title'=>'用户组名称','rules'=>'用户组拥有的规则id,多个,号隔开'), 142 * ...) 143 */ 144 public function getGroups($uid) { 145 static $groups = array(); 146 if (isset($groups[$uid])) 147 return $groups[$uid]; 148 $user_groups = \think\Db::name($this->_config['auth_group_access']) 149 ->alias('a') 150 ->join($this->_config['auth_group']." g", "g.id=a.group_id") 151 ->where("a.uid='$uid' and g.status='1'") 152 ->field('uid,group_id,title,rules')->select(); 153 $groups[$uid] = $user_groups ? $user_groups : array(); 154 return $groups[$uid]; 155 } 156 157 /** 158 * 获得权限列表 159 * @param integer $uid 用户id 160 * @param integer $type 161 */ 162 protected function getAuthList($uid,$type) { 163 static $_authList = array(); //保存用户验证通过的权限列表 164 $t = implode(',',(array)$type); 165 if (isset($_authList[$uid.$t])) { 166 return $_authList[$uid.$t]; 167 } 168 if( $this->_config['auth_type']==2 && isset($_SESSION['_auth_list_'.$uid.$t])){ 169 return $_SESSION['_auth_list_'.$uid.$t]; 170 } 171 172 //读取用户所属用户组 173 $groups = $this->getGroups($uid); 174 $ids = array();//保存用户所属用户组设置的所有权限规则id 175 foreach ($groups as $g) { 176 $ids = array_merge($ids, explode(',', trim($g['rules'], ','))); 177 } 178 $ids = array_unique($ids); 179 if (empty($ids)) { 180 $_authList[$uid.$t] = array(); 181 return array(); 182 } 183 184 $map=array( 185 'id'=>array('in',$ids), 186 'type'=>$type, 187 'status'=>1, 188 ); 189 //读取用户组所有权限规则 190 $rules = \think\Db::name($this->_config['auth_rule'])->where($map)->field('condition,name')->select(); 191 192 //循环规则,判断结果。 193 $authList = array(); // 194 foreach ($rules as $rule) { 195 if (!empty($rule['condition'])) { //根据condition进行验证 196 $user = $this->getUserInfo($uid);//获取用户信息,一维数组 197 198 $command = preg_replace('/\{(\w*?)\}/', '$user[\'\\1\']', $rule['condition']); 199 //dump($command);//debug 200 @(eval('$condition=(' . $command . ');')); 201 if ($condition) { 202 $authList[] = strtolower($rule['name']); 203 } 204 } else { 205 //只要存在就记录 206 $authList[] = strtolower($rule['name']); 207 } 208 } 209 $_authList[$uid.$t] = $authList; 210 if($this->_config['auth_type']==2){ 211 //规则列表结果保存到session 212 $_SESSION['_auth_list_'.$uid.$t]=$authList; 213 } 214 return array_unique($authList); 215 } 216 217 /** 218 * 获得用户资料,根据自己的情况读取数据库 219 */ 220 protected function getUserInfo($uid) { 221 static $userinfo=array(); 222 if(!isset($userinfo[$uid])){ 223 $userinfo[$uid]=\think\Db::name($this->_config['auth_user'])->where(array('uid'=>$uid))->find(); 224 } 225 return $userinfo[$uid]; 226 } 227 228 }
那么有了这个类,怎么用它呢?其实很简单,复制注释中的sql语句,建立三张表,然后写一个公共的类继承控制器类,然后在需要验证权限的类中继承这个公共类就行了,下面附上这个公共类Common.php
1 <?php 2 /** 3 * 作者:魏安来 4 * 功能:后台公共类,控制后台权限 5 * 日期:2017/11/13 6 */ 7 namespace app\admin\controller; 8 use think\Controller; 9 use think\Session; 10 use think\Request; 11 12 class Common extends Controller { 13 14 /** 15 * 初始化方法 16 * 功能:验证权限 17 */ 18 public function _initialize() { 19 /*判断用户是否有Session,没有就退出登录*/ 20 if(!Session::get('uid')) { 21 $this->redirect('login/index'); 22 } 23 24 $request = Request::instance(); 25 $auth = new Auth(); 26 27 /*************验证权限*************/ 28 $controller = $this->uncamelize(request()->controller()); 29 $name = $controller.'/'.request()->action(); 30 $res = $auth->check($name,Session::get('uid')); 31 //定义一个数组,放置可以不限制权限的页面 32 $noCheck = ['index/index','index/logout']; 33 //超级管理员不用验证权限 34 $superadmin = $auth->getGroups(Session::get('uid')); 35 if($superadmin[0]['group_id'] != 1) { 36 if(!in_array($name,$noCheck)) { 37 if(!$res) { 38 $this->error('你没有权限'); 39 } 40 } 41 } 42 } 43 44 45 /** 46 * 驼峰命名转下划线命名 47 * 思路: 48 * 小写和大写紧挨一起的地方,加上分隔符,然后全部转小写 49 */ 50 public function uncamelize($camelCaps,$separator='_') 51 { 52 return strtolower(preg_replace('/([a-z])([A-Z])/', "$1" . $separator . "$2", $camelCaps)); 53 } 54 55 } 56 57 ?>
这样就搞定了权限验证了.不过原则上没有权限不应该显示的,上面的验证方法可以阻止企图绕过权限验证的行为,比如直接在地址栏输入链接访问,所以上面应该的权限验证应该算是隐形的防线,关于没有权限的用户不显示,可以参考下面的写法,我就直接附上代码了:
1 /** 2 * 功能:显示菜单 3 */ 4 public function menu() { 5 /*获取所有菜单*/ 6 $allmenu = \think\Db::name('menu')->where(1)->select(); 7 /*查询二级菜单*/ 8 $res = db('menu')->where('pid','<>',0)->where('isshow','=',1)->order('sort asc')->select(); 9 $auth = new Auth(); 10 $superadmin = $auth->getGroups(Session::get('uid')); 11 if($superadmin[0]['group_id'] != 1) {//超级管理员不需要验证权限 12 foreach($allmenu as $key=>$value) { 13 $rules[$key] = $value['controller'].'/'.$value['method']; 14 } 15 //获取权限规则 16 $authList = $auth->getAuthList(Session::get('uid'),1); 17 //数组交集 18 $intersection = array_intersect($rules,$authList); 19 $arrtmp = array(); 20 //将一维数组拼接成二维数组 21 foreach($intersection as $key=>$val){ 22 $tempArr = explode('/',$val); 23 $arrtmp[$key]['controller'] = $tempArr[0]; 24 } 25 $intersection = $arrtmp; 26 $menuArr = array(); 27 //筛选符合权限的数组,重新组成左侧导航菜单数据 28 foreach($allmenu as $key=>$value){ 29 foreach($intersection as $val){ 30 if(!empty(array_intersect($val,$value))){ 31 $menuArr[$key] = $value; 32 } 33 } 34 } 35 $allmenu = $menuArr; 36 //筛选符合权限的数组,重新组成左侧导航菜单数据 37 foreach($res as $key=>$value){ 38 foreach($intersection as $val){ 39 if(!empty(array_intersect($val,$value))){ 40 $resArr[$key] = $value; 41 } 42 } 43 } 44 $res = $resArr; 45 } 46 $num = count($allmenu); 47 $this->view->assign('child_menu',$res); 48 $this->view->assign('num',$num); 49 $this->view->assign('allmenu',$allmenu); 50 }
转载于:https://www.cnblogs.com/walblog/p/7930048.html
ThinkPHP5权限控制相关推荐
- mysql用户控制登录_MySql用户权限控制_MySQL
bitsCN.com MySql用户权限控制 本文将介绍MySql创建帐号,删除帐号,设置和介绍各种帐号的权限 创建用户帐号: www.bitsCN.com [sql] CREATE USER use ...
- 前、后端分离权限控制设计和实现思路
点击上方"方志朋",选择"设为星标" 回复"666"获取新整理的面试文章 来源:8rr.co/9QUT 简述 近几年随着react.angu ...
- cvs linux权限,Linux下CVS+ACL的权限控制是什么? 爱问知识人
考试大Linux站整理:我的CVS服务器端是在linux下,我安装了cvs-1.11.22-cvsacl-1.2.5-patched.tar.gz,利用CVS+ACL来做权限控制.但是现在遇到几个问题 ...
- Java访问权限控制
面向对象的核心思想之一就是封装,只把有限的方法和成员公开给别人,这也是迪米特法则的内在要求,是外部调用方对方法体内的实现细节知道得尽可能少. 如何实现封装呢? 需要使用某些关键字来限制外部对类内属性和 ...
- 基于RESTful API 怎么设计用户权限控制?
作者:JC_Huang http://www.jianshu.com/p/db65cf48c111 1 前言 有人说,每个人都是平等的: 也有人说,人生来就是不平等的: 在人类社会中,并没有绝对的 ...
- 8.Spring Security 权限控制
Spring Security权限控制可以配合授权注解使用,具体有哪些注解可以参考Spring-Security保护方法.接着上一节,要开启这些注解,只需要在Spring Security配置文件中添 ...
- 2.Spring Security 用户注销 与 Thymeleaf 权限控制
Spring Security 用户注销 与 Thymeleaf 权限控制 Spring Security 用户注销 1.上一篇<Spring Security 详细简绍与入门>中内存用户 ...
- SAP QM 权限控制可以到Inspection Type上
SAP QM 权限控制可以到Inspection Type上 比如我是以一个仓库operator的账号去试图显示一个检验批, 系统报错:You do not have authorization fo ...
- 通用数据级别权限的框架设计与实现(4)-单条记录的权限控制
查看上篇文章通用数据级别权限的框架设计与实现(3)-数据列表的权限过滤,我们开始在原来的基础上实现单条权记录的权限控制. 相信前面的列表权限控制,很多系统都可以做到,但如何在上面列表的权限过滤中实现通 ...
- springmvc+spring+mybatis+maven项目集成shiro进行用户权限控制【转】
项目结构: 1.maven项目的pom中引入shiro所需的jar包依赖关系 ? 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 ...
最新文章
- 和12岁小同志搞创客开发:如何选择合适的控制器?
- Caffe将自己的文件生成lmdb
- PAT甲级1072 Gas Station (30 分):[C++题解]dijkstra算法、最短路
- openresty开发系列13--lua基础语法2常用数据类型介绍
- python 十六进制转中文_Python列表中包含中文时输出十六进制转中文的小方法
- windows之tracert与linux之traceroute用法详解
- SharePoint Timer Job
- 迷宫问题---递归解决
- 赞!清华大学发布首个自动图机器学习工具包AutoGL
- iOS - UIActivityIndicatorView
- Oracle工作中常用函数的总结
- v50进9008救砖
- 群晖NAS系统DSM入门
- 淘宝店铺层级作用 店铺层级低有哪些影响
- MySQL登录出错:ERROR 2003 (HY000): Can't connect to MySQL server on 'localhost' (10061)
- 实现三级导航demo
- 图虫知识共享协议_100%避免图片版权侵权的方法(网站图片侵权赔款标准)
- b站python直播批量发送弹幕_python实现b站直播自动发送弹幕功能
- 快速搭建python文件服务器,上传下载文件,快速搭建。
- 手机浏览器上网谁最快?手机浏览器速度测评
热门文章
- python连点封闭多边形_python实现根据给定坐标点生成多边形mask的例子
- Java之数组(上)
- centos镜像 from_Docker 基于 CentOS 基础镜像开发环境的搭建与部署
- linux apache支持ipv6,如何在Nginx和Apache中启用IPv6?
- C++ int与string互转换
- java代码pingip_java代码ping一个IP地址
- gtx1050ti最稳定的驱动_最便宜图灵吃鸡卡 华硕GTX 1650评测
- Hibernate中一二级缓存使用详解
- webapi 状态返回 php,让WebAPI 返回JSON格式的数据实例教程
- 小D课堂-SpringBoot 2.x微信支付在线教育网站项目实战_5-5.HttpClient4.x工具获取使用...