thinkphp5的Auth权限认证实战
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权限认证实战的更多相关文章
- thinkphp5的auth权限认证(转自thinkphp官方文档+自己总结)
thinkphp5的auth权限认证(转自thinkphp官方文档+自己总结) 一.总结 一句话总结:相当于就是用其它thinkphp的扩展一样,都是引入扩展,配置扩展,然后使用 引入 配置 使用 基 ...
- auth权限认证详细讲解
auth权限认证详细讲解 一.总结 一句话总结:四表两组关系,一个多对多(权限和用户组之间)(多对多需要3个表),一个一对多(用户和用户组之间) 1.实际上使用Auth是需要4张表的(1.会员表 2. ...
- Thinkphp5 Auth权限认证
Thinkphp5 Auth权限认证 一.总结 一句话总结:四表两组关系,一个多对多(权限和用户组之间),一个一对多(用户和用户组之间) 二.Thinkphp5 Auth权限认证 auth类在thin ...
- Thinkphp基于规则的Auth权限认证类
PS:onethink是基于该权限认证类实现,Auth类作为官方类库,在Library\Think里面. 其实Auth类也是基于角色访问控制RBAC扩展的,具体到节点的权限校验方式还是需要根据业务 ...
- 比RBAC更好的权限认证方式(Auth类认证)
Auth 类已经在ThinkPHP代码仓库中存在很久了,但是因为一直没有出过它的教程, 很少人知道它, 它其实比RBAC更方便 . RBAC是按节点进行认证的,如果要控制比节点更细的权限就有点困难了, ...
- thinkphp Auth认证类 比RBAC更好的权限认证方式(Auth类认证)
thinkphp Auth认证类 比RBAC更好的权限认证方式(Auth类认证) Auth 类已经在ThinkPHP代码仓库中存在很久了,但是因为一直没有出过它的教程, 很少人知道它, 它其实比 ...
- thinkphp 比RBAC更好的权限认证方式(Auth类认证)
Auth 类已经在ThinkPHP代码仓库中存在很久了,但是因为一直没有出过它的教程, 很少人知道它, 它其实比RBAC更方便 . RBAC是按节点进行认证的,如果要控制比节点更细的权限就有点困难了, ...
- ThinkPHP的Auth类认证
Auth 类已经在ThinkPHP代码仓库中存在很久了,但是因为一直没有出过它的教程, 很少人知道它, 它其实比RBAC更方便 . RBAC是按节点进行认证的,如果要控制比节点更细的权限就有点困难了 ...
- Hangfire实战二——为DashBoard页面添加权限认证
概述 Hangfire Dashboard为我们提供了可视化的对后台任务进行管理的界面,我们可以直接在这个页面上对定时任务进行删除.立即执行等操作,如下图所示: 默认情况下,这个页面只能在部署Hang ...
随机推荐
- Python爬虫(三)——对豆瓣图书各模块评论数与评分图形化分析
文化 经管 ....略 结论: 一个模块的评分与评论数相关,评分为 [8.8——9.2] 之间的书籍评论数往往是模块中最多的
- sed/awk advance
$ echo test.file [Group1]cacheways = 19 [Group2]cacheways = 19 $ ls test.sh FILE=test.file2 # Set Gr ...
- mysql主从(主备)同步一键配置,配自动检测功能
主从一键shell配置 做个笔记. #!/bin/bash #Mysql sync #chenglee #master机器ip MasterIP="192.168.137.174" ...
- mint-ui之Loadmore使用
<template> <div class="page-loadmore"> <div class="page-loadmore-wrapp ...
- 值类型之间的相互转化,运算符,if条件判断,循环,函数
值类型之间的相互转化 number | string | boolean 一.转换为boolean=>Boolean(a); var num = 10; var s = '123'; var b ...
- SVM学习笔记5-SMO
首先拿出最后要求解的问题:$\underset{\alpha}{min}W(\alpha)=\frac{1}{2} \sum_{i,j=1}^{n}y^{(i)}y^{(j)}\alpha_{i}\a ...
- 题解——洛谷P2827 NOIP提高组 2016 蚯蚓
队列模拟 详细题解待填坑 #include <cstdio> #include <algorithm> #include <queue> #include < ...
- [POJ 3984] 迷宫问题(BFS最短路径的记录和打印问题)
题目链接:http://poj.org/problem?id=3984 宽度优先搜索最短路径的记录和打印问题 #include<iostream> #include<queue> ...
- [HDU 1215] 七夕节(求因子,不超时)
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=1215 //注意怎么处理不超时 #include<iostream> #include< ...
- Python数据类型补充2
四.列表 常用操作+内置的方法: 1.按索引存取值(正向存取+反向存取):即可存也可以取 # li=['a','b','c','d'] # print(li[-1]) # li[-1]='D' # p ...