我在用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权限控制相关推荐

  1. mysql用户控制登录_MySql用户权限控制_MySQL

    bitsCN.com MySql用户权限控制 本文将介绍MySql创建帐号,删除帐号,设置和介绍各种帐号的权限 创建用户帐号: www.bitsCN.com [sql] CREATE USER use ...

  2. 前、后端分离权限控制设计和实现思路

    点击上方"方志朋",选择"设为星标" 回复"666"获取新整理的面试文章 来源:8rr.co/9QUT 简述 近几年随着react.angu ...

  3. cvs linux权限,Linux下CVS+ACL的权限控制是什么? 爱问知识人

    考试大Linux站整理:我的CVS服务器端是在linux下,我安装了cvs-1.11.22-cvsacl-1.2.5-patched.tar.gz,利用CVS+ACL来做权限控制.但是现在遇到几个问题 ...

  4. Java访问权限控制

    面向对象的核心思想之一就是封装,只把有限的方法和成员公开给别人,这也是迪米特法则的内在要求,是外部调用方对方法体内的实现细节知道得尽可能少. 如何实现封装呢? 需要使用某些关键字来限制外部对类内属性和 ...

  5. 基于RESTful API 怎么设计用户权限控制?

    作者:JC_Huang http://www.jianshu.com/p/db65cf48c111 1   前言 有人说,每个人都是平等的: 也有人说,人生来就是不平等的: 在人类社会中,并没有绝对的 ...

  6. 8.Spring Security 权限控制

    Spring Security权限控制可以配合授权注解使用,具体有哪些注解可以参考Spring-Security保护方法.接着上一节,要开启这些注解,只需要在Spring Security配置文件中添 ...

  7. 2.Spring Security 用户注销 与 Thymeleaf 权限控制

    Spring Security 用户注销 与 Thymeleaf 权限控制 Spring Security 用户注销 1.上一篇<Spring Security 详细简绍与入门>中内存用户 ...

  8. SAP QM 权限控制可以到Inspection Type上

    SAP QM 权限控制可以到Inspection Type上 比如我是以一个仓库operator的账号去试图显示一个检验批, 系统报错:You do not have authorization fo ...

  9. 通用数据级别权限的框架设计与实现(4)-单条记录的权限控制

    查看上篇文章通用数据级别权限的框架设计与实现(3)-数据列表的权限过滤,我们开始在原来的基础上实现单条权记录的权限控制. 相信前面的列表权限控制,很多系统都可以做到,但如何在上面列表的权限过滤中实现通 ...

  10. 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 ...

最新文章

  1. 和12岁小同志搞创客开发:如何选择合适的控制器?
  2. Caffe将自己的文件生成lmdb
  3. PAT甲级1072 Gas Station (30 分):[C++题解]dijkstra算法、最短路
  4. openresty开发系列13--lua基础语法2常用数据类型介绍
  5. python 十六进制转中文_Python列表中包含中文时输出十六进制转中文的小方法
  6. windows之tracert与linux之traceroute用法详解
  7. SharePoint Timer Job
  8. 迷宫问题---递归解决
  9. 赞!清华大学发布首个自动图机器学习工具包AutoGL
  10. iOS - UIActivityIndicatorView
  11. Oracle工作中常用函数的总结
  12. v50进9008救砖
  13. 群晖NAS系统DSM入门
  14. 淘宝店铺层级作用 店铺层级低有哪些影响
  15. MySQL登录出错:ERROR 2003 (HY000): Can't connect to MySQL server on 'localhost' (10061)
  16. 实现三级导航demo
  17. 图虫知识共享协议_100%避免图片版权侵权的方法(网站图片侵权赔款标准)
  18. b站python直播批量发送弹幕_python实现b站直播自动发送弹幕功能
  19. 快速搭建python文件服务器,上传下载文件,快速搭建。
  20. 手机浏览器上网谁最快?手机浏览器速度测评

热门文章

  1. python连点封闭多边形_python实现根据给定坐标点生成多边形mask的例子
  2. Java之数组(上)
  3. centos镜像 from_Docker 基于 CentOS 基础镜像开发环境的搭建与部署
  4. linux apache支持ipv6,如何在Nginx和Apache中启用IPv6?
  5. C++ int与string互转换
  6. java代码pingip_java代码ping一个IP地址
  7. gtx1050ti最稳定的驱动_最便宜图灵吃鸡卡 华硕GTX 1650评测
  8. Hibernate中一二级缓存使用详解
  9. webapi 状态返回 php,让WebAPI 返回JSON格式的数据实例教程
  10. 小D课堂-SpringBoot 2.x微信支付在线教育网站项目实战_5-5.HttpClient4.x工具获取使用...