久久精品人人爽,华人av在线,亚洲性视频网站,欧美专区一二三

RBAC權(quán)限控制的實現(xiàn)原理

148次閱讀
沒有評論

共計 6491 個字符,預(yù)計需要花費 17 分鐘才能閱讀完成。

本篇內(nèi)容介紹了“RBAC 權(quán)限控制的實現(xiàn)原理”的有關(guān)知識,在實際案例的操作過程中,不少人都會遇到這樣的困境,接下來就讓丸趣 TV 小編帶領(lǐng)大家學(xué)習(xí)一下如何處理這些情況吧!希望大家仔細(xì)閱讀,能夠?qū)W有所成!

       RBAC 是英文 Role-based Access Control 的首字母縮寫,中文意思是基礎(chǔ)角色的權(quán)限控制,它是一種思想,根據(jù) RBAC 思想進(jìn)行數(shù)據(jù)表設(shè)計, 更好的完成不同角色的對應(yīng)的權(quán)限控制。

        如何使用 RBAC 思想進(jìn)行數(shù)據(jù)表的設(shè)計

        如果我們的項目允許一個后臺管理用戶可能有 1 個或者 2 個及 2 個以上的多個角色, 按照下面進(jìn)行設(shè)計:

    權(quán)限菜單表,角色表,用戶表是互相獨立的。設(shè)計表的順序是權(quán)限菜單表,角色表,用戶表,用戶 - 角色關(guān)聯(lián)表。

   1. 首先是權(quán)限菜單表設(shè)計如下:

    注意:權(quán)限菜單可以是多級菜單,添加 pid 字段,方便無限極遞歸分類。

   2. 角色表設(shè)計如下:

   3. 用戶表設(shè)計如下:

   4. 最后是用戶 - 角色關(guān)聯(lián)表設(shè)計如下:

   

    當(dāng)超級管理員在后臺需要添加新用戶時,不僅需要 insert 數(shù)據(jù)進(jìn)用戶表,也需要在用戶 - 角色表中添加用戶和角色的關(guān)系。與之對應(yīng),刪除用戶時,也需要將用戶 - 角色表中對應(yīng)的用戶 - 角色關(guān)系刪除。

public function add()
 { if(request()- isPost()){
 $role_id = input( post.role_id 
 $data = [  uname = input( post.uname),
  pwd = password_hash(input( post.pwd),PASSWORD_BCRYPT),
  login_ip = request()- ip(),
  status = input(post.status),
  create_time = time(),
 ];
 $uid = Db::name(users)- insertGetId($data);
 if($uid){
 $data = [
  uid = $uid,
  role_id = $role_id
 ];
 $id = Db::name(users_role)- insertGetId($data);
 if($id)
 {
 echo  true 
 exit;
 }else{
 echo  false 
 exit;
 }
 }else{
 echo  false 
 exit;
 }
 }else{
 // 獲取所有角色
 $role = Db::name(auth_role)- field(id,title)- order(id , asc)- where(status ,1)- select();
 return view(add ,[ role = $role]);
 }
 
 }

  這樣以來我們根據(jù)用戶登錄以后 session 中儲存的 uid 判斷當(dāng)前登錄用戶的身份信息,根據(jù)獲取到的 uid 查詢用戶 - 角色關(guān)聯(lián)表查詢到用戶的角色 id, 然后到角色表獲取到該用戶可操作的權(quán)限菜單。

    封裝中間控制器 Common.php

?php
namespace app\admin\controller;
use app\BaseController;
use think\facade\Session;
use lib\Auth;/** 權(quán)限認(rèn)證類 **/
class Common extends BaseController
 public function initialize(){
 $sess_auth = session( uid 
 $uname = session( uname 
 
 // 判斷用戶是否登錄
 if(!$sess_auth){
 jumpTo( /login/index 
 exit;
 // 檢查到用戶登錄后,  還要檢測該用戶是否具有操作某個頁面的權(quán)限, (是否具有操作某個方法的權(quán)限)
 }else{ $auth = new Auth();
 if(!$auth- check(request()- controller(). / .request()- action(),$sess_auth)){
 historyTo( 抱歉~ 你沒有操作該欄目的權(quán)限,請聯(lián)系管理員! 
 exit;
 }
 }
 }
}

lib\Auth;/** 權(quán)限認(rèn)證類 **/
   

?php
use think\facade\Db;
use think\facade\Config;
use think\facade\Session;
use think\facade\Request;

 protected $_config = [   auth_on  =  true, //  認(rèn)證開關(guān)   auth_type  =  1, //  認(rèn)證方式,1 為實時認(rèn)證;2 為登錄認(rèn)證。  auth_role  =   auth_role , //  用戶組數(shù)據(jù)表名   users_role  =   users_role , //  用戶 - 用戶組關(guān)系表   auth_rule  =   auth_rule , //  權(quán)限規(guī)則表   auth_user  =   users , //  用戶信息表    ];    public function __construct()  { if (Config::get( app.auth)) {  $this- _config = array_merge($this- _config, Config::get( app.auth  }  }    /**  *  檢查權(quán)限  * @param string|array $name  需要驗證的規(guī)則列表,支持逗號分隔的權(quán)限規(guī)則或索引數(shù)組  * @param integer $uid  認(rèn)證用戶 ID  * @param string $relation  如果為   or   表示滿足任一條規(guī)則即通過驗證; 如果為   and   則表示需滿足所有規(guī)則才能通過驗證  * @param string $mode  執(zhí)行 check 的模式  * @param integer $type  規(guī)則類型  * @return boolean  通過驗證返回 true; 失敗返回 false  */  public function check($name, $uid, $relation =  or , $mode =  url , $type = 1)  { 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];  }  }  $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); //  解析規(guī)則中的 param  $intersect = array_intersect_assoc($REQUEST, $param);  $auth = preg_replace(/\?.*$/U ,  , $auth);  if (in_array($auth, $name)   $intersect == $param) { $list[] = $auth;  }  } elseif (in_array($auth, $name)) { $list[] = $auth;  }  }  if ($relation ===  or    !empty($list)) {  return true;  }  $diff = array_diff($name, $list);  if ($relation ===  and    empty($diff)) {  return true;  }  return false;  }  /**  *  根據(jù)用戶 ID 獲取用戶組,返回值為數(shù)組  * @param integer $uid  用戶 ID  * @return array  用戶所屬用戶組  [uid = 用戶 ID ,  group_id = 用戶組 ID ,  title = 用戶組名 ,  rules = 用戶組擁有的規(guī)則 ID,多個用英文, 隔開]  */  public function getGroups($uid)  { static $groups = [];  if (isset($groups[$uid])) { return $groups[$uid];  }  $user_groups = Db::name($this- _config[ users_role])  - alias(ur)  - where(ur.uid , $uid)  - where(ar.status , 1)  - join($this- _config[ auth_role].  ar ,  ur.role_id = ar.id )  - field(uid,role_id,title,rules)  - select();  $groups[$uid] = $user_groups ?: [];  return $groups[$uid];  }  /**  *  獲得權(quán)限列表  * @param integer $uid  用戶 ID  * @param integer $type  規(guī)則類型  * @return array  權(quán)限列表  */  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 = []; //  保存用戶所屬用戶組設(shè)置的所有權(quán)限規(guī)則 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]  ];  //  讀取用戶組所有權(quán)限規(guī)則  $rules = Db::name($this- _config[ auth_rule])- where($map)- field(condition,name)- select();  //  循環(huán)規(guī)則,判斷結(jié)果。 $authList = [];  foreach ($rules as $rule) { if (!empty($rule[ condition])) { //  根據(jù) condition 進(jìn)行驗證  $user = $this- getUserInfo($uid); //  獲取用戶信息, 一維數(shù)組  $command = preg_replace(/\{(\w*?)\}/ ,  $user[\ \\1\] , $rule[ condition  // dump($command); // debug  @(eval( $condition=( .$command.  if ($condition) { $authList[] = strtolower($rule[ name  }  } else {  //  只要存在就記錄  $authList[] = strtolower($rule[ name  }  }  $_authList[$uid.$t] = $authList;  if ($this- _config[ auth_type] == 2) { Session::set( _AUTH_LIST_ .$uid.$t, $authList);  }  return array_unique($authList);  }  /**  *  獲得用戶資料, 根據(jù)自己的情況讀取數(shù)據(jù)庫  */  protected function getUserInfo($uid) { static $user_info = [];  $user = Db::name($this- config[ auth_user  //  獲取用戶表主鍵  $_pk = is_string($user- getPk()) ? $user- getPk() :  uid  if (!isset($user_info[$uid])) { $user_info[$uid] = $user- where($_pk, $uid)- find();  }  return $user_info[$uid];  } }

    這樣就能實現(xiàn)路由操作權(quán)限的實時檢測,比如我們讓首頁控制器繼承中間控制器:

?php
namespace app\admin\controller;
use think\Request;
use think\facade\Db;//db 類
use think\facade\Session;
use lib\Rule;
class Index extends Common
 public function index()
 { 
 $uname = session( uname 
 $uid = session( uid 
 //  根據(jù) uid, 獲取該用戶相應(yīng)的權(quán)限, 連表查詢
 $res = Db::name(users)- alias(u)- where(u.uid ,$uid)
 - leftJoin(users_role ur , ur.uid = u.uid)
 - leftJoin(auth_role ar , ar.id = ur.role_id)
 - field(u.uid,u.uname,ar.rules)
 - select()- toArray();
 // dd($res);
 $rules = implode( , ,array_column($res, rules 
 // dd( $rules);
 //in 查詢   根據(jù)獲取到的 rules id  選權(quán)限列表
 $res = Db::name(auth_rule)- field(id,name,title,pid)- order(id , asc)- where(is_menu ,1)
 - where(id , in ,$rules)- select();
 // dump($res);
 // 這里使用擴(kuò)展類 Rule 中封裝的無限極分類方法
 $rlist = Rule::Rulelayer($res);
 // dd($rlist);
 $data = [
  uid = $uid,
  uname = $uname,
  rlist = $rlist,
  create_time = 1617252175
 ];
 return view(index , $data);
 
 }
 }

最終實現(xiàn)的效果如圖:

“RBAC 權(quán)限控制的實現(xiàn)原理”的內(nèi)容就介紹到這里了,感謝大家的閱讀。如果想了解更多行業(yè)相關(guān)的知識可以關(guān)注丸趣 TV 網(wǎng)站,丸趣 TV 小編將為大家輸出更多高質(zhì)量的實用文章!

正文完
 
丸趣
版權(quán)聲明:本站原創(chuàng)文章,由 丸趣 2023-07-28發(fā)表,共計6491字。
轉(zhuǎn)載說明:除特殊說明外本站除技術(shù)相關(guān)以外文章皆由網(wǎng)絡(luò)搜集發(fā)布,轉(zhuǎn)載請注明出處。
評論(沒有評論)
主站蜘蛛池模板: 黎平县| 新河县| 仲巴县| 平谷区| 安溪县| 仲巴县| 沽源县| 宜良县| 赤壁市| 平泉县| 达日县| 竹山县| 贵定县| 祁门县| 昌黎县| 绥阳县| 岳池县| 东至县| 普安县| 承德市| 台中市| 报价| 维西| 靖江市| 隆昌县| 甘孜| 平阴县| 景宁| 太和县| 广州市| 湟中县| 随州市| 博野县| 永宁县| 阿勒泰市| 普兰店市| 江山市| 蓬安县| 榆林市| 四子王旗| 巍山|