thinkphp5的Auth權限認證明戰

thinkphp5的Auth權限認證明戰

1、總結

一句話總結:基於角色的權限管理(真正作一遍,就會發現很簡單,否則一直都是半懂不懂的

基於角色的權限管理

真正作一遍,就會發現很簡單,否則一直都是半懂不懂的php

 

一、Auth權限認證步驟?

a、創建auth表
b、權限界面

a、創建auth表html

改auth表名前端

各個表字段的意思thinkphp

能夠在基礎表的基礎上增長咱們須要的字段數據庫

好比排序字段,好比無限級分類的pid字段(好比規則表上面就須要)apache

 

b、權限界面後端

用戶組管理數組

規則管理session

 

老師端/管理員端(管理端板塊佈局)app

權限管理------

------用戶組管理

------規則管理

------------添加規則(上級規則)

 

二、Auth權限類怎麼引入系統?

直接把Auth.php丟到要用的控制器的那個文件夾中便可
也能夠用composer的方式弄進來

直接把Auth.php丟到要用的控制器的那個文件夾中便可

全部的權限認證均可以這麼弄的

這樣都在同一個文件夾下面,命名空間都是同樣的以後,能夠直接new 的方式引入類

 

其實也能夠用composer的方式弄進來,應該都是直接給你引入好了的

 

三、Auth類的控制應該放到哪裏?

基礎控制器的初始化方法裏面

獲取當前控制器和當前方法的名稱(也是Auth類的使用方法)

這個方法仍是放到基礎控制器的初始化方法裏面的

 

 

四、Auth類具體驗證是如何進行的?

獲取當前控制器和當前方法的名稱 + 和數據表中的當前控制器和方法對比一下就好

獲取當前控制器和當前方法的名稱(也是Auth類的使用方法)

這個方法仍是放到基礎控制器的初始化方法裏面的

 

 

 

五、權限選擇界面如何實現?

tree結構

選擇下級功能的時候默認選擇到上級的

因此在獲取下級id的時候也是默認須要選擇上級的id(其實也不須要,到時候看狀況作就行了)

用戶組來選擇權限,來選擇哪些權限爲你開放

 

 

六、前端的權限控制如何實現?

獲取當前控制器和當前方法的名稱 + 和html中寫的控制器和方法名作對比

 

前端按鈕的隱藏不用作,由於會給你一個沒有權限的返回頁面,由於權限的控制語句是寫在基礎控制器的初始化方法裏面的

 

若是實現,能夠結合後端實現,也能夠用權限數字大小來判斷

 

七、Beyandadmin簡單模板中如何直接從beyand的樣式中獲取表格?

直接把對應的html代碼複製下來就行了

直接獲取

把對應的html代碼整下來就行了

 

八、作系統,或者作啥子功能,最早,也是最須要的操做是什麼?

設計

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

 

九、Auth權限認證的時候,改不改默認的數據表字段?

若是改了的話,那麼Auth類要一塊兒改,其實改起來也很簡單

否則Auth類就很差用了,由於Auth.php就是根據默認的字段來寫的

若是改了的話,那麼Auth類要一塊兒改,其實改起來也很簡單

 

十、Auth權限類的使用?

直接把Auth.php放進控制器,而後注意命名空間,而後調用new類調用方法便可

直接把Auth.php放進控制器,而後注意命名空間,而後調用new類調用方法便可

use app\admin2\controller\Auth;

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

 

 

十一、如何獲取當前控制器的當前方法?

Request實例的controller和action方法

Request實例的controller和action方法

原生php裏面就有方法能夠取當前類名和方法名

thinkphp5裏面只是對原生方法進行了一點封裝而已

1         $request=Request::instance();
2         //當前控制器
3         $con=$request->controller();
4         //當前方法
5         $action=$request->action();
6         $name=$con.'/'.$action;
7         //dump($name);die;

 

 

 

十二、Auth權限認證的實質是什麼?

拿當前控制器的當前方法和你填寫好的Auth_rule裏面的控制字段作對比

拿當前控制器的當前方法和你填寫好的Auth_rule裏面的控制字段作對比

這是當前控制器的當前方法
string(19) "Authority.admin/add"

那麼auth_rule表裏面的控制字段也應該是相應的格式

 

 1     //權限驗證
 2     public function doAuthority(){
 3         $auth=new Auth();
 4         $request=Request::instance();
 5         //當前控制器
 6         $con=$request->controller();
 7         //當前方法
 8         $action=$request->action();
 9         $name=$con.'/'.$action;
10         //dump($name);die;
11         if($auth->check($name,session('id'))){
12             $this->error('Failed,No Permission.(失敗,沒有權限)',url('index/index'));
13         }
14     }

 

1三、Auth權限認證的核心代碼?

new Auth類,而後調用check方法便可,注意參數name爲當前控制器的當前方法

new Auth類,而後調用check方法便可,注意參數name爲當前控制器的當前方法

 1     //權限驗證
 2     public function doAuthority(){
 3         $auth=new Auth();
 4         $request=Request::instance();
 5         //當前控制器
 6         $con=$request->controller();
 7         //當前方法
 8         $action=$request->action();
 9         $name=$con.'/'.$action;
10         //dump($name);die;
11         if($auth->check($name,session('id'))){
12             $this->error('Failed,No Permission.(失敗,沒有權限)',url('index/index'));
13         }
14     }

 

 

1四、在Auth權限認證中如何給某些特權用戶加特權(好比超級管理員不用進行權限認證)?

直接在權限認證的位置加特判便可,

直接在權限認證的位置加特判便可,

因此能夠進行各類特判

 1     //權限驗證
 2     public function doAuthority(){
 3         $auth=new Auth();
 4         $request=Request::instance();
 5         //當前控制器
 6         $con=$request->controller();
 7         //當前方法
 8         $action=$request->action();
 9         $name=$con.'/'.$action;
10         //dump($name);die;
11 
12         //超級管理員無需權限驗證
13         $auth_group=$auth->getGroups(session('id'));
14         //dump($auth_group);die;
15         if(isset($auth_group[0]['aga_ag_id'])&&$auth_group[0]['aga_ag_id']==3){
16 
17         }else{
18             if(!$auth->check($name,session('id'))){
19                 $this->error('Failed,No Permission.',url('index/index'));
20             }
21         }
22         //
23 
24     }

 

1五、如何指定某些頁面不進行權限認證?

用數組將不進行權限認證的頁面弄出來,而後進行特判便可

用數組將不進行權限認證的頁面弄出來,而後進行特判便可

頁面能夠用控制器/方法來表示

16  //某些頁面不進行權限認證 17 $notCheck=array('Index/index');
 1     //權限驗證
 2     public function doAuthority(){
 3         $auth=new Auth();
 4         $request=Request::instance();
 5         //當前控制器
 6         $con=$request->controller();
 7         //當前方法
 8         $action=$request->action();
 9         $name=$con.'/'.$action;
10         //dump($name);die;
11 
12         //超級管理員無需權限驗證
13         $auth_group=$auth->getGroups(session('id'));
14         //dump($auth_group);die;
15 
16         //某些頁面不進行權限認證
17         $notCheck=array('Index/index');
18         if(isset($auth_group[0]['aga_ag_id'])&&$auth_group[0]['aga_ag_id']==3){
19 
20         }else{
21             if(!in_array($name,$notCheck)){
22                 if(!$auth->check($name,session('id'))){
23                     $this->error('Failed,No Permission.',url('index/index'));
24                 }
25             }
26         }
27         //
28 
29     }

 

1六、Auth權限認證整個流程實質?

給用戶分到權限組
給權限組指定規則
規則能夠"控制器/方法名"的方式表示
而後那用戶對應的權限組的"控制器/方法名"的數組和當前控制器/當前方法作比較,符合條件則讓進入頁面,不然不讓

 

1七、Auth權限是後端的權限,前端的權限怎麼解決?

獲取當前控制器和當前方法的名稱 + 和html中寫的控制器和方法名作對比

加上類,直接js實現,簡單方便,並且方便開發

分爲三類:

管理員端的東西:好比跨班級的東西

老師端的東西:好比提交系統反饋啊

本人的東西:好比資源的修改刪除,

加js類作統一控制

好比資源的修改刪除,是管理員也能夠,而後老師本人也能夠,可是本班的別的老師不行

 

 

2、Auth權限認證核心代碼

一、驗證的代碼

這裏注意auth類的引入

use app\admin2\controller\Auth;

驗證是在基礎控制器的初始化方法中

class Base extends Controller
{
    //任何一個方法執行都會調用這個方法
    public function _initialize()
    {
        $this->doAuthority();
    }

 

 1     //權限驗證
 2     public function doAuthority(){
 3         $auth=new Auth();
 4         $request=Request::instance();
 5         //當前控制器
 6         $con=$request->controller();
 7         //當前方法
 8         $action=$request->action();
 9         $name=$con.'/'.$action;
10         //dump($name);die;
11 
12         //超級管理員無需權限驗證
13         $auth_group=$auth->getGroups(session('id'));
14         //dump($auth_group);die;
15 
16         //某些頁面不進行權限認證
17         $notCheck=array('Index/index');
18         if(isset($auth_group[0]['aga_ag_id'])&&$auth_group[0]['aga_ag_id']==3){
19 
20         }else{
21             if(!in_array($name,$notCheck)){
22                 if(!$auth->check($name,session('id'))){
23                     $this->error('Failed,No Permission.',url('index/index'));
24                 }
25             }
26         }
27         //
28 
29     }

 

二、驗證類及數據表

數據表最好不要動,若是動了的話,記得改下面方法裏面的字段

  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 namespace app\admin\controller;
 12 use think\Config;
 13 use think\Session;
 14 use think\Db;
 15 /**
 16  * 權限認證類
 17  * 功能特性:
 18  * 1,是對規則進行認證,不是對節點進行認證。用戶能夠把節點看成規則名稱實現對節點進行認證。
 19  *      $auth=new Auth();  $auth->check('規則名稱','用戶id')
 20  * 2,能夠同時對多條規則進行認證,並設置多條規則的關係(or或者and)
 21  *      $auth=new Auth();  $auth->check('規則1,規則2','用戶id','and') 
 22  *      第三個參數爲and時表示,用戶須要同時具備規則1和規則2的權限。 當第三個參數爲or時,表示用戶值須要具有其中一個條件便可。默認爲or
 23  * 3,一個用戶能夠屬於多個用戶組(think_auth_group_access表 定義了用戶所屬用戶組)。咱們須要設置每一個用戶組擁有哪些規則(think_auth_group 定義了用戶組權限)
 24  * 
 25  * 4,支持規則表達式。
 26  *      在think_auth_rule 表中定義一條規則時,若是type爲1, condition字段就能夠定義規則表達式。 如定義{score}>5  and {score}<100  表示用戶的分數在5-100之間時這條規則纔會經過。
 27  */
 28 //數據庫
 29 /*
 30   -- ----------------------------
 31   -- bk_auth_rule,規則表,
 32   -- id:主鍵,name:規則惟一標識, title:規則中文名稱 status 狀態:爲1正常,爲0禁用,condition:規則表達式,爲空表示存在就驗證,不爲空表示按照條件驗證
 33   -- ----------------------------
 34   DROP TABLE IF EXISTS `bk_auth_rule`;
 35   CREATE TABLE `bk_auth_rule` (
 36   `id` mediumint(8) unsigned NOT NULL AUTO_INCREMENT,
 37   `name` char(80) NOT NULL DEFAULT '',
 38   `title` char(20) NOT NULL DEFAULT '',
 39   `type` tinyint(1) NOT NULL DEFAULT '1',
 40   `status` tinyint(1) NOT NULL DEFAULT '1',
 41   `condition` char(100) NOT NULL DEFAULT '',  # 規則附件條件,知足附加條件的規則,才認爲是有效的規則
 42   PRIMARY KEY (`id`),
 43   UNIQUE KEY `name` (`name`)
 44   ) ENGINE=MyISAM  DEFAULT CHARSET=utf8;
 45   -- ----------------------------
 46   -- bk_auth_group 用戶組表,
 47   -- id:主鍵, title:用戶組中文名稱, rules:用戶組擁有的規則id, 多個規則","隔開,status 狀態:爲1正常,爲0禁用
 48   -- ----------------------------
 49   DROP TABLE IF EXISTS `bk_auth_group`;
 50   CREATE TABLE `bk_auth_group` (
 51   `id` mediumint(8) unsigned NOT NULL AUTO_INCREMENT,
 52   `title` char(100) NOT NULL DEFAULT '',
 53   `status` tinyint(1) NOT NULL DEFAULT '1',
 54   `rules` char(80) NOT NULL DEFAULT '',
 55   PRIMARY KEY (`id`)
 56   ) ENGINE=MyISAM  DEFAULT CHARSET=utf8;
 57   -- ----------------------------
 58   -- bk_auth_group_access 用戶組明細表
 59   -- uid:用戶id,group_id:用戶組id
 60   -- ----------------------------
 61   DROP TABLE IF EXISTS `bk_auth_group_access`;
 62   CREATE TABLE `bk_auth_group_access` (
 63   `uid` mediumint(8) unsigned NOT NULL,
 64   `group_id` mediumint(8) unsigned NOT NULL,
 65   UNIQUE KEY `uid_group_id` (`uid`,`group_id`),
 66   KEY `uid` (`uid`),
 67   KEY `group_id` (`group_id`)
 68   ) ENGINE=MyISAM DEFAULT CHARSET=utf8;
 69  */
 70 
 71 class Auth {
 72     //默認配置
 73     protected $config = array(
 74         'auth_on'           => true,                      // 認證開關
 75         'auth_type'         => 2,                         // 認證方式,1爲實時認證;2爲登陸認證。
 76         'auth_group'        => 'auth_group',        // 用戶組數據表名
 77         'auth_group_access' => 'auth_group_access', // 用戶-用戶組關係表
 78         'auth_rule'         => 'auth_rule',         // 權限規則表
 79         'auth_user'         => 'auth_member'             // 用戶信息表
 80     );
 81     
 82     public function __construct() {
 83         if (Config::get('auth_config')) {
 84             $this->config = array_merge($this->config, Config::get('auth_config')); //可設置配置項 auth_config, 此配置項爲數組。
 85         }
 86     }
 87     /**
 88      * 檢查權限
 89      * @param name string|array  須要驗證的規則列表,支持逗號分隔的權限規則或索引數組
 90      * @param uid  int           認證用戶的id
 91      * @param string mode        執行check的模式
 92      * @param relation string    若是爲 'or' 表示知足任一條規則即經過驗證;若是爲 'and'則表示需知足全部規則才能經過驗證
 93      * return boolean           經過驗證返回true;失敗返回false
 94      */
 95     public function check($name, $uid, $type = 1, $mode = 'url', $relation = 'or') {
 96         if (!$this->config['auth_on']) {
 97             return true;
 98         }
 99         $authList = $this->getAuthList($uid, $type); //獲取用戶須要驗證的全部有效規則列表
100         if (is_string($name)) {
101             $name = strtolower($name);
102 //            if (strpos($name, ',') !== false) {
103 //                $name = explode(',', $name);
104 //            } else {
105 //                $name = [$name];
106 //            }
107             $name = strpos($name, ',') !== false ? explode(',', $name) : [$name];
108         }
109         $list = []; //保存驗證經過的規則名
110         if ($mode == 'url') {
111             $REQUEST = unserialize(strtolower(serialize($_REQUEST)));
112         }
113         foreach ($authList as $auth) {
114             $query = preg_replace('/^.+\?/U', '', $auth);
115             if ($mode == 'url' && $query != $auth) {
116                 parse_str($query, $param); //解析規則中的param
117                 $intersect = array_intersect_assoc($REQUEST, $param);
118                 $auth = preg_replace('/\?.*$/U', '', $auth);
119                 if (in_array($auth, $name) && $intersect == $param) {  //若是節點相符且url參數知足
120                     $list[] = $auth;
121                 }
122             } else if (in_array($auth, $name)) {
123                 $list[] = $auth;
124             }
125         }
126         if ($relation == 'or' and ! empty($list)) {
127             return true;
128         }
129         $diff = array_diff($name, $list);
130         if ($relation == 'and' and empty($diff)) {
131             return true;
132         }
133         return false;
134     }
135     /**
136      * 根據用戶id獲取用戶組,返回值爲數組
137      * @param  uid int     用戶id
138      * return array       用戶所屬的用戶組 [
139      *     ['uid'=>'用戶id','group_id'=>'用戶組id','title'=>'用戶組名稱','rules'=>'用戶組擁有的規則id,多個,號隔開'),
140      *     ...)   
141      */
142     public function getGroups($uid) {
143         static $groups = [];
144         if (isset($groups[$uid])) {
145             return $groups[$uid];
146         }
147         $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")
148                         ->where(['uid' => $uid, 'status' => 1])->select();
149         $groups[$uid] = $user_groups ? $user_groups : [];
150         return $groups[$uid];
151     }
152     /**
153      * 得到權限列表
154      * @param integer $uid  用戶id
155      * @param integer $type 
156      */
157     protected function getAuthList($uid, $type) {
158         static $_authList = []; //保存用戶驗證經過的權限列表
159         $t = implode(',', (array) $type);
160         if (isset($_authList[$uid . $t])) {
161             return $_authList[$uid . $t];
162         }
163         if ($this->config['auth_type'] == 2 && Session::has('_auth_list_' . $uid . $t)) {
164             return Session::get('_auth_list_' . $uid . $t);
165         }
166         //讀取用戶所屬用戶組
167         $groups = $this->getGroups($uid);
168         $ids = []; //保存用戶所屬用戶組設置的全部權限規則id
169         foreach ($groups as $g) {
170             $ids = array_merge($ids, explode(',', trim($g['rules'], ',')));
171         }
172         $ids = array_unique($ids);
173         if (empty($ids)) {
174             $_authList[$uid . $t] = [];
175             return [];
176         }
177         $map = [
178             'id' => ['in', $ids],
179             'type' => $type,
180             'status' => 1,
181         ];
182         //讀取用戶組全部權限規則
183         $rules = Db::name($this->config['auth_rule'])->where($map)->field('condition,name')->select();
184         //循環規則,判斷結果。
185         $authList = [];   //
186         foreach ($rules as $rule) {
187             if (!empty($rule['condition'])) { //根據condition進行驗證
188                 $this->getUserInfo($uid); //獲取用戶信息,一維數組
189                 $command = preg_replace('/\{(\w*?)\}/', '$user[\'\\1\']', $rule['condition']);
190                 @(eval('$condition=(' . $command . ');'));
191                 $condition && $authList[] = strtolower($rule['name']);
192             } else {
193                 $authList[] = strtolower($rule['name']); //只要存在就記錄
194             }
195         }
196         $_authList[$uid . $t] = $authList;
197         if ($this->config['auth_type'] == 2) {
198             $_SESSION['_auth_list_' . $uid . $t] = $authList; //規則列表結果保存到session
199         }
200         return array_unique($authList);
201     }
202     /**
203      * 得到用戶資料,根據本身的狀況讀取數據庫
204      */
205     protected function getUserInfo($uid) {
206         static $userinfo = [];
207         if (!isset($userinfo[$uid])) {
208             $userinfo[$uid] = Db::name($this->config['auth_user'])->where(['uid' => $uid])->find();
209         }
210         return $userinfo[$uid];
211     }
212 }
相關文章
相關標籤/搜索