thinkphp5的Auth权限认证实战

一、总结

一句话总结:基于角色的权限管理(真正做一遍,就会发现很简单,不然一直都是半懂不懂的)

基于角色的权限管理

真正做一遍,就会发现很简单,不然一直都是半懂不懂的

1、Auth权限认证步骤?

a、建立auth表
b、权限界面

a、建立auth表

改auth表名

各个表字段的意思

可以在基础表的基础上增加我们需要的字段

比如排序字段,比如无限级分类的pid字段(比如规则表上面就需要)

b、权限界面

用户组管理

规则管理

老师端/管理员端(管理端板块布局)

权限管理------

------用户组管理

------规则管理

------------添加规则(上级规则)

2、Auth权限类怎么引入系统?

直接把Auth.php丢到要用的控制器的那个文件夹中即可
也可以用composer的方式弄进来

直接把Auth.php丢到要用的控制器的那个文件夹中即可

所有的权限认证都可以这么弄的

这样都在同一个文件夹下面,命名空间都是一样的之后,可以直接new 的方式引入类

其实也可以用composer的方式弄进来,应该都是直接给你引入好了的

3、Auth类的控制应该放到哪里?

基础控制器的初始化方法里面

获取当前控制器和当前方法的名称(也是Auth类的使用方法)

这个方法还是放到基础控制器的初始化方法里面的

4、Auth类具体验证是如何进行的?

获取当前控制器和当前方法的名称 + 和数据表中的当前控制器和方法对比一下就好

获取当前控制器和当前方法的名称(也是Auth类的使用方法)

这个方法还是放到基础控制器的初始化方法里面的

5、权限选择界面如何实现?

tree结构

选择下级功能的时候默认选择到上级的

所以在获取下级id的时候也是默认需要选择上级的id(其实也不需要,到时候看情况做就好了)

用户组来选择权限,来选择哪些权限为你开放

6、前端的权限控制如何实现?

获取当前控制器和当前方法的名称 + 和html中写的控制器和方法名做对比

前端按钮的隐藏不用做,因为会给你一个没有权限的返回页面,因为权限的控制语句是写在基础控制器的初始化方法里面的

如果实现,可以结合后端实现,也可以用权限数字大小来判断

7、Beyandadmin简单模板中如何直接从beyand的样式中获取表格?

直接把对应的html代码复制下来就好了

直接获取

把对应的html代码整下来就好了

8、做系統,或者做啥子功能,最先,也是最需要的操作是什麼?

设计

做設計,先把界面以及功能設計出來,梳理清楚了,自然也就清楚了。

9、Auth权限认证的时候,改不改默认的数据表字段?

如果改了的话,那么Auth类要一起改,其实改起来也很简单

不然Auth类就不好用了,因为Auth.php就是根据默认的字段来写的

如果改了的话,那么Auth类要一起改,其实改起来也很简单

10、Auth权限类的使用?

直接把Auth.php放进控制器,然后注意命名空间,然后调用new类调用方法即可

直接把Auth.php放进控制器,然后注意命名空间,然后调用new类调用方法即可

use app\admin2\controller\Auth;

        $auth=new Auth();
$group=$auth->getGroups(session('id'));
dump($group);die;

11、如何获取当前控制器的当前方法?

Request实例的controller和action方法

Request实例的controller和action方法

原生php里面就有方法可以取当前类名和方法名

thinkphp5里面只是对原生方法进行了一点封装而已

         $request=Request::instance();
//當前控制器
$con=$request->controller();
//當前方法
$action=$request->action();
$name=$con.'/'.$action;
//dump($name);die;

12、Auth权限认证的实质是什么?

拿当前控制器的当前方法和你填写好的Auth_rule里面的控制字段做对比

拿当前控制器的当前方法和你填写好的Auth_rule里面的控制字段做对比

这是当前控制器的当前方法
string(19) "Authority.admin/add" 那么auth_rule表里面的控制字段也应该是相应的格式
     //權限驗證
public function doAuthority(){
$auth=new Auth();
$request=Request::instance();
//當前控制器
$con=$request->controller();
//當前方法
$action=$request->action();
$name=$con.'/'.$action;
//dump($name);die;
if($auth->check($name,session('id'))){
$this->error('Failed,No Permission.(失敗,沒有權限)',url('index/index'));
}
}

13、Auth权限认证的核心代码?

new Auth类,然后调用check方法即可,注意参数name为当前控制器的当前方法

new Auth类,然后调用check方法即可,注意参数name为当前控制器的当前方法

     //權限驗證
public function doAuthority(){
$auth=new Auth();
$request=Request::instance();
//當前控制器
$con=$request->controller();
//當前方法
$action=$request->action();
$name=$con.'/'.$action;
//dump($name);die;
if($auth->check($name,session('id'))){
$this->error('Failed,No Permission.(失敗,沒有權限)',url('index/index'));
}
}

14、在Auth权限认证中如何给某些特权用户加特权(比如超级管理员不用进行权限认证)?

直接在权限认证的位置加特判即可,

直接在权限认证的位置加特判即可,

所以可以进行各种特判

     //權限驗證
public function doAuthority(){
$auth=new Auth();
$request=Request::instance();
//當前控制器
$con=$request->controller();
//當前方法
$action=$request->action();
$name=$con.'/'.$action;
//dump($name);die; //超級管理員無需權限驗證
$auth_group=$auth->getGroups(session('id'));
//dump($auth_group);die;
if(isset($auth_group[0]['aga_ag_id'])&&$auth_group[0]['aga_ag_id']==3){ }else{
if(!$auth->check($name,session('id'))){
$this->error('Failed,No Permission.',url('index/index'));
}
}
// }

15、如何指定某些页面不进行权限认证?

用数组将不进行权限认证的页面弄出来,然后进行特判即可

用数组将不进行权限认证的页面弄出来,然后进行特判即可

页面可以用控制器/方法来表示

16         //某些頁面不進行權限認證
17 $notCheck=array('Index/index');
     //權限驗證
public function doAuthority(){
$auth=new Auth();
$request=Request::instance();
//當前控制器
$con=$request->controller();
//當前方法
$action=$request->action();
$name=$con.'/'.$action;
//dump($name);die; //超級管理員無需權限驗證
$auth_group=$auth->getGroups(session('id'));
//dump($auth_group);die; //某些頁面不進行權限認證
$notCheck=array('Index/index');
if(isset($auth_group[0]['aga_ag_id'])&&$auth_group[0]['aga_ag_id']==3){ }else{
if(!in_array($name,$notCheck)){
if(!$auth->check($name,session('id'))){
$this->error('Failed,No Permission.',url('index/index'));
}
}
}
// }

16、Auth权限认证整个流程实质?

给用户分到权限组
给权限组指定规则
规则可以"控制器/方法名"的方式表示
然后那用户对应的权限组的"控制器/方法名"的数组和当前控制器/当前方法做比较,符合条件则让进入页面,否则不让

17、Auth权限是后端的权限,前端的权限怎么解决?

获取当前控制器和当前方法的名称 + 和html中写的控制器和方法名做对比

加上类,直接js实现,简单方便,而且方便开发

分为三类:

管理员端的东西:比如跨班级的东西

老师端的东西:比如提交系统反馈啊

本人的东西:比如资源的修改删除,

加js类做统一控制

比如资源的修改删除,是管理员也可以,然后老师本人也可以,但是本班的别的老师不行

二、Auth权限认证核心代码

1、验证的代码

这里注意auth类的引入

use app\admin2\controller\Auth;

验证是在基础控制器的初始化方法中

class Base extends Controller
{
//任何一个方法执行都会调用这个方法
public function _initialize()
{
$this->doAuthority();
}
     //權限驗證
public function doAuthority(){
$auth=new Auth();
$request=Request::instance();
//當前控制器
$con=$request->controller();
//當前方法
$action=$request->action();
$name=$con.'/'.$action;
//dump($name);die; //超級管理員無需權限驗證
$auth_group=$auth->getGroups(session('id'));
//dump($auth_group);die; //某些頁面不進行權限認證
$notCheck=array('Index/index');
if(isset($auth_group[0]['aga_ag_id'])&&$auth_group[0]['aga_ag_id']==3){ }else{
if(!in_array($name,$notCheck)){
if(!$auth->check($name,session('id'))){
$this->error('Failed,No Permission.',url('index/index'));
}
}
}
// }

2、验证类及数据表

数据表最好不要动,如果动了的话,记得改下面方法里面的字段

 <?php
// +----------------------------------------------------------------------
// | ThinkPHP [ WE CAN DO IT JUST THINK IT ]
// +----------------------------------------------------------------------
// | Copyright (c) 2011 http://thinkphp.cn All rights reserved.
// +----------------------------------------------------------------------
// | Licensed ( http://www.apache.org/licenses/LICENSE-2.0 )
// +----------------------------------------------------------------------
// | Author: luofei614 <weibo.com/luofei614> 
// +----------------------------------------------------------------------
namespace app\admin\controller;
use think\Config;
use think\Session;
use think\Db;
/**
* 权限认证类
* 功能特性:
* 1,是对规则进行认证,不是对节点进行认证。用户可以把节点当作规则名称实现对节点进行认证。
* $auth=new Auth(); $auth->check('规则名称','用户id')
* 2,可以同时对多条规则进行认证,并设置多条规则的关系(or或者and)
* $auth=new Auth(); $auth->check('规则1,规则2','用户id','and')
* 第三个参数为and时表示,用户需要同时具有规则1和规则2的权限。 当第三个参数为or时,表示用户值需要具备其中一个条件即可。默认为or
* 3,一个用户可以属于多个用户组(think_auth_group_access表 定义了用户所属用户组)。我们需要设置每个用户组拥有哪些规则(think_auth_group 定义了用户组权限)
*
* 4,支持规则表达式。
* 在think_auth_rule 表中定义一条规则时,如果type为1, condition字段就可以定义规则表达式。 如定义{score}>5 and {score}<100 表示用户的分数在5-100之间时这条规则才会通过。
*/
//数据库
/*
-- ----------------------------
-- bk_auth_rule,规则表,
-- id:主键,name:规则唯一标识, title:规则中文名称 status 状态:为1正常,为0禁用,condition:规则表达式,为空表示存在就验证,不为空表示按照条件验证
-- ----------------------------
DROP TABLE IF EXISTS `bk_auth_rule`;
CREATE TABLE `bk_auth_rule` (
`id` mediumint(8) unsigned NOT NULL AUTO_INCREMENT,
`name` char(80) NOT NULL DEFAULT '',
`title` char(20) NOT NULL DEFAULT '',
`type` tinyint(1) NOT NULL DEFAULT '1',
`status` tinyint(1) NOT NULL DEFAULT '1',
`condition` char(100) NOT NULL DEFAULT '', # 规则附件条件,满足附加条件的规则,才认为是有效的规则
PRIMARY KEY (`id`),
UNIQUE KEY `name` (`name`)
) ENGINE=MyISAM DEFAULT CHARSET=utf8;
-- ----------------------------
-- bk_auth_group 用户组表,
-- id:主键, title:用户组中文名称, rules:用户组拥有的规则id, 多个规则","隔开,status 状态:为1正常,为0禁用
-- ----------------------------
DROP TABLE IF EXISTS `bk_auth_group`;
CREATE TABLE `bk_auth_group` (
`id` mediumint(8) unsigned NOT NULL AUTO_INCREMENT,
`title` char(100) NOT NULL DEFAULT '',
`status` tinyint(1) NOT NULL DEFAULT '1',
`rules` char(80) NOT NULL DEFAULT '',
PRIMARY KEY (`id`)
) ENGINE=MyISAM DEFAULT CHARSET=utf8;
-- ----------------------------
-- bk_auth_group_access 用户组明细表
-- uid:用户id,group_id:用户组id
-- ----------------------------
DROP TABLE IF EXISTS `bk_auth_group_access`;
CREATE TABLE `bk_auth_group_access` (
`uid` mediumint(8) unsigned NOT NULL,
`group_id` mediumint(8) unsigned NOT NULL,
UNIQUE KEY `uid_group_id` (`uid`,`group_id`),
KEY `uid` (`uid`),
KEY `group_id` (`group_id`)
) ENGINE=MyISAM DEFAULT CHARSET=utf8;
*/ class Auth {
//默认配置
protected $config = array(
'auth_on' => true, // 认证开关
'auth_type' => 2, // 认证方式,1为实时认证;2为登录认证。
'auth_group' => 'auth_group', // 用户组数据表名
'auth_group_access' => 'auth_group_access', // 用户-用户组关系表
'auth_rule' => 'auth_rule', // 权限规则表
'auth_user' => 'auth_member' // 用户信息表
); public function __construct() {
if (Config::get('auth_config')) {
$this->config = array_merge($this->config, Config::get('auth_config')); //可设置配置项 auth_config, 此配置项为数组。
}
}
/**
* 检查权限
* @param name string|array 需要验证的规则列表,支持逗号分隔的权限规则或索引数组
* @param uid int 认证用户的id
* @param string mode 执行check的模式
* @param relation string 如果为 'or' 表示满足任一条规则即通过验证;如果为 'and'则表示需满足所有规则才能通过验证
* return boolean 通过验证返回true;失败返回false
*/
public function check($name, $uid, $type = 1, $mode = 'url', $relation = 'or') {
if (!$this->config['auth_on']) {
return true;
}
$authList = $this->getAuthList($uid, $type); //获取用户需要验证的所有有效规则列表
if (is_string($name)) {
$name = strtolower($name);
// if (strpos($name, ',') !== false) {
// $name = explode(',', $name);
// } else {
// $name = [$name];
// }
$name = strpos($name, ',') !== false ? explode(',', $name) : [$name];
}
$list = []; //保存验证通过的规则名
if ($mode == 'url') {
$REQUEST = unserialize(strtolower(serialize($_REQUEST)));
}
foreach ($authList as $auth) {
$query = preg_replace('/^.+\?/U', '', $auth);
if ($mode == 'url' && $query != $auth) {
parse_str($query, $param); //解析规则中的param
$intersect = array_intersect_assoc($REQUEST, $param);
$auth = preg_replace('/\?.*$/U', '', $auth);
if (in_array($auth, $name) && $intersect == $param) { //如果节点相符且url参数满足
$list[] = $auth;
}
} else if (in_array($auth, $name)) {
$list[] = $auth;
}
}
if ($relation == 'or' and ! empty($list)) {
return true;
}
$diff = array_diff($name, $list);
if ($relation == 'and' and empty($diff)) {
return true;
}
return false;
}
/**
* 根据用户id获取用户组,返回值为数组
* @param uid int 用户id
* return array 用户所属的用户组 [
* ['uid'=>'用户id','group_id'=>'用户组id','title'=>'用户组名称','rules'=>'用户组拥有的规则id,多个,号隔开'),
* ...)
*/
public function getGroups($uid) {
static $groups = [];
if (isset($groups[$uid])) {
return $groups[$uid];
}
$user_groups = Db::view($this->config['auth_group_access'], 'uid,group_id')->view($this->config['auth_group'], 'title,rules', "{$this->config['auth_group_access']}.group_id={$this->config['auth_group']}.id")
->where(['uid' => $uid, 'status' => 1])->select();
$groups[$uid] = $user_groups ? $user_groups : [];
return $groups[$uid];
}
/**
* 获得权限列表
* @param integer $uid 用户id
* @param integer $type
*/
protected function getAuthList($uid, $type) {
static $_authList = []; //保存用户验证通过的权限列表
$t = implode(',', (array) $type);
if (isset($_authList[$uid . $t])) {
return $_authList[$uid . $t];
}
if ($this->config['auth_type'] == 2 && Session::has('_auth_list_' . $uid . $t)) {
return Session::get('_auth_list_' . $uid . $t);
}
//读取用户所属用户组
$groups = $this->getGroups($uid);
$ids = []; //保存用户所属用户组设置的所有权限规则id
foreach ($groups as $g) {
$ids = array_merge($ids, explode(',', trim($g['rules'], ',')));
}
$ids = array_unique($ids);
if (empty($ids)) {
$_authList[$uid . $t] = [];
return [];
}
$map = [
'id' => ['in', $ids],
'type' => $type,
'status' => 1,
];
//读取用户组所有权限规则
$rules = Db::name($this->config['auth_rule'])->where($map)->field('condition,name')->select();
//循环规则,判断结果。
$authList = []; //
foreach ($rules as $rule) {
if (!empty($rule['condition'])) { //根据condition进行验证
$this->getUserInfo($uid); //获取用户信息,一维数组
$command = preg_replace('/\{(\w*?)\}/', '$user[\'\\1\']', $rule['condition']);
@(eval('$condition=(' . $command . ');'));
$condition && $authList[] = strtolower($rule['name']);
} else {
$authList[] = strtolower($rule['name']); //只要存在就记录
}
}
$_authList[$uid . $t] = $authList;
if ($this->config['auth_type'] == 2) {
$_SESSION['_auth_list_' . $uid . $t] = $authList; //规则列表结果保存到session
}
return array_unique($authList);
}
/**
* 获得用户资料,根据自己的情况读取数据库
*/
protected function getUserInfo($uid) {
static $userinfo = [];
if (!isset($userinfo[$uid])) {
$userinfo[$uid] = Db::name($this->config['auth_user'])->where(['uid' => $uid])->find();
}
return $userinfo[$uid];
}
}
 

thinkphp5的Auth权限认证实战的更多相关文章

  1. thinkphp5的auth权限认证(转自thinkphp官方文档+自己总结)

    thinkphp5的auth权限认证(转自thinkphp官方文档+自己总结) 一.总结 一句话总结:相当于就是用其它thinkphp的扩展一样,都是引入扩展,配置扩展,然后使用 引入 配置 使用 基 ...

  2. auth权限认证详细讲解

    auth权限认证详细讲解 一.总结 一句话总结:四表两组关系,一个多对多(权限和用户组之间)(多对多需要3个表),一个一对多(用户和用户组之间) 1.实际上使用Auth是需要4张表的(1.会员表 2. ...

  3. Thinkphp5 Auth权限认证

    Thinkphp5 Auth权限认证 一.总结 一句话总结:四表两组关系,一个多对多(权限和用户组之间),一个一对多(用户和用户组之间) 二.Thinkphp5 Auth权限认证 auth类在thin ...

  4. Thinkphp基于规则的Auth权限认证类

      PS:onethink是基于该权限认证类实现,Auth类作为官方类库,在Library\Think里面. 其实Auth类也是基于角色访问控制RBAC扩展的,具体到节点的权限校验方式还是需要根据业务 ...

  5. 比RBAC更好的权限认证方式(Auth类认证)

    Auth 类已经在ThinkPHP代码仓库中存在很久了,但是因为一直没有出过它的教程, 很少人知道它, 它其实比RBAC更方便 . RBAC是按节点进行认证的,如果要控制比节点更细的权限就有点困难了, ...

  6. thinkphp Auth认证类 比RBAC更好的权限认证方式(Auth类认证)

    thinkphp Auth认证类 比RBAC更好的权限认证方式(Auth类认证)    Auth 类已经在ThinkPHP代码仓库中存在很久了,但是因为一直没有出过它的教程, 很少人知道它, 它其实比 ...

  7. thinkphp 比RBAC更好的权限认证方式(Auth类认证)

    Auth 类已经在ThinkPHP代码仓库中存在很久了,但是因为一直没有出过它的教程, 很少人知道它, 它其实比RBAC更方便 . RBAC是按节点进行认证的,如果要控制比节点更细的权限就有点困难了, ...

  8. ThinkPHP的Auth类认证

    Auth 类已经在ThinkPHP代码仓库中存在很久了,但是因为一直没有出过它的教程, 很少人知道它, 它其实比RBAC更方便 .  RBAC是按节点进行认证的,如果要控制比节点更细的权限就有点困难了 ...

  9. Hangfire实战二——为DashBoard页面添加权限认证

    概述 Hangfire Dashboard为我们提供了可视化的对后台任务进行管理的界面,我们可以直接在这个页面上对定时任务进行删除.立即执行等操作,如下图所示: 默认情况下,这个页面只能在部署Hang ...

随机推荐

  1. 缩点:Power Plant;

    题目传送门:[UVALive 6437]Power Plant 题目大意:T组数据,给定一幅带权图(n, m), 然后给定k个点, 与图中存在有若干条边.每个点都要至少要和这k个点的一个点直接或间接相 ...

  2. <线程池-定时任务> ScheduledExecutorService之shutdown引发的RejectedExecutionException问题

    一. 问题描述 先来看一下异常信息,启动tomcat时就报错: 2015-3-20 15:22:39 org.apache.catalina.core.StandardContext listener ...

  3. 学习Struts2的个人疑惑及问题解决

    刚开始学习SSH框架中Struts2时,个人疑惑以及一些问题总结一下. 1.package节点namespace属性值决定访问路径问题       namespace不写或写namespace=&qu ...

  4. topcoder srm list

    300 305 310 315 320 325 330 335 340 350 360 370 380 390 400 410 415 420 425 430 435 440 445 450 455 ...

  5. 如果此表在它的 ChildRelation 集合中不是父表,则不能将关系添加到该集合中。

    今天遇到这个问题头都大了,百度上也没找到解决方案,就自己在哪里沉思................ 终于皇天不负有心人,被我解决了! 这是调用ChildRelations.Add(“名字”,“父级”, ...

  6. Restful framework【第五篇】解析器

    基本使用 -解析器 -源码从request.data -全局配置 -'DEFAULT_PARSER_CLASSES':['rest_framework.parsers.JSONParser'], -局 ...

  7. P4782 【模板】2-SAT 问题

    https://www.luogu.org/problemnew/show/P4782 链接 https://www.luogu.org/problemnew/show/P4782 思路 选a就必须选 ...

  8. (转) AI突破性论文及代码实现汇总

    本文转自:https://zhuanlan.zhihu.com/p/25191377 AI突破性论文及代码实现汇总 极视角 · 2 天前 What Can AI Do For You? “The bu ...

  9. Unity3D代码动态修改材质球的颜色

    代码动态修改材质球的颜色: gameObject.GetComponent<Renderer>().material.color=Color.red;//当材质球的Shader为标准时,可 ...

  10. facebook ads api

    api测试 https://developers.facebook.com/tools/explorer/517735271920003?method=GET&path=act_1107316 ...