thinkphp5 中的權(quán)限認證模塊

1.數(shù)據(jù)庫結(jié)構(gòu)

用戶表

CREATE TABLE `think_user` (

`id` int(11) NOT NULL AUTO_INCREMENT, //主鍵id

`username` varchar(30) DEFAULT NULL, //用戶名

`password` varchar(32) DEFAULT NULL, //密碼

PRIMARY KEY (`id`)

) ENGINE=InnoDB AUTO_INCREMENT=6 DEFAULT CHARSET=utf8;

權(quán)限節(jié)點表

CREATE TABLE `think_auth_rule` (

`id` mediumint(8) unsigned NOT NULL AUTO_INCREMENT, //主鍵id

`name` char(80) NOT NULL DEFAULT '' COMMENT '規(guī)則唯一標(biāo)識', //描述

`url` char(20) NOT NULL DEFAULT '' COMMENT '規(guī)則中文名稱', //路徑如:Index/index

`status` tinyint(1) NOT NULL DEFAULT '1' COMMENT '狀態(tài):為1正常,為0禁用',

`pcontroller` char(80) NOT NULL, //上次控制器

`condition` char(100) NOT NULL DEFAULT '' COMMENT '規(guī)則表達式,為空表示存在就驗證,不為空表示按照條件驗',

`type` tinyint(1) NOT NULL DEFAULT '1',

PRIMARY KEY (`id`),

UNIQUE KEY `name` (`name`)

) ENGINE=MyISAM AUTO_INCREMENT=11 DEFAULT CHARSET=utf8 COMMENT='規(guī)則表';

用戶組--用戶關(guān)聯(lián)表

CREATE TABLE `think_auth_group_access` (

`uid` mediumint(8) unsigned NOT NULL COMMENT '用戶id',

`group_id` mediumint(8) unsigned NOT NULL COMMENT '用戶組id',

UNIQUE KEY `uid_group_id` (`uid`,`group_id`),

KEY `uid` (`uid`),

KEY `group_id` (`group_id`)

) ENGINE=MyISAM DEFAULT CHARSET=utf8 COMMENT='用戶組明細表';

用戶組表

CREATE TABLE `think_auth_group` (

`id` mediumint(8) unsigned NOT NULL AUTO_INCREMENT, //主鍵id

`name` char(100) NOT NULL DEFAULT '',//用戶組名稱

`status` tinyint(1) NOT NULL DEFAULT '1',//用戶組狀態(tài)

`rules` char(80) NOT NULL DEFAULT '',//用戶組關(guān)聯(lián)的權(quán)限節(jié)點id(多個)

PRIMARY KEY (`id`)

) ENGINE=MyISAM AUTO_INCREMENT=9 DEFAULT CHARSET=utf8 COMMENT='用戶組表';

2.認證類

classAuth{

//默認配置

protected$_config= array(

'AUTH_ON'=> true,//認證開關(guān)

'AUTH_TYPE'=>1,//認證方式,1為實時認證;2為登錄認證。

'AUTH_GROUP'=>'think_auth_group',//用戶組數(shù)據(jù)表名

'AUTH_GROUP_ACCESS'=>'think_auth_group_access',//用戶-用戶組關(guān)系表

'AUTH_RULE'=>'think_auth_rule',//權(quán)限規(guī)則表

'AUTH_USER'=>'think_user'//用戶信息表

);

public function__construct() {

header("Content-type: text/html; charset=utf-8");

if(Config::get('auth_config')) {

$this->_config=array_merge($this->_config,Config::get('auth_config'));//可設(shè)置配置項auth_config,此配置項為數(shù)組。

}

}

/**

*檢查權(quán)限

* @param name string|array需要驗證的規(guī)則列表,支持逗號分隔的權(quán)限規(guī)則或索引數(shù)組

* @param uid? int認證用戶的id

* @param string mode執(zhí)行check的模式

* @param relation string如果為'or'表示滿足任一條規(guī)則即通過驗證;如果為'and'則表示需滿足所有規(guī)則才能通過驗證

* @return boolean通過驗證返回true;失敗返回false

*/

public functioncheck($name,$uid,$type=1,$mode='url',$relation='or') {

if(!$this->_config['AUTH_ON'])

return true;

$authList=$this->getAuthList($uid,$type);//獲取用戶需要驗證的所有有效規(guī)則列表

if(is_string($name)) {

$name=strtolower($name);

$name=strpos($name,',')!== false ?explode(',',$name): array($name);

}

$list= array();//保存驗證通過的規(guī)則名

if($mode=='url') {

$REQUEST=unserialize(strtolower(serialize($_REQUEST)) );

}

foreach($authListas$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) {//如果節(jié)點相符且url參數(shù)滿足

$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;

}

/**

*根據(jù)用戶id獲取用戶組,返回值為數(shù)組

* @param? uid int用戶id

* @return array用戶所屬的用戶組array(

*? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? array('uid'=>'用戶id','group_id'=>'用戶組id','title'=>'用戶組名稱','rules'=>'用戶組擁有的規(guī)則id,多個,號隔開'),

*? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ...)

*/

public functiongetGroups($uid) {

static$groups= array();

if(isset($groups[$uid]))

return$groups[$uid];

$user_groups=Db::view($this->_config['AUTH_GROUP_ACCESS'],'uid,group_id')->view($this->_config['AUTH_GROUP'],'name,rules',"{$this->_config['AUTH_GROUP_ACCESS']}.group_id={$this->_config['AUTH_GROUP']}.id")

->where(['uid'=>$uid,'status'=>1])->select();

$groups[$uid]=$user_groups?:array();

return$groups[$uid];

}

/**

*獲得權(quán)限列表

* @param integer $uid用戶id

* @param integer $type

*/

protected functiongetAuthList($uid,$type) {

static$_authList= array();//保存用戶驗證通過的權(quán)限列表

$t=implode(',',(array)$type);

if(isset($_authList[$uid.$t])) {

return$_authList[$uid.$t];

}

if($this->_config['AUTH_TYPE']==2&& isset($_SESSION['_AUTH_LIST_'.$uid.$t])){

return$_SESSION['_AUTH_LIST_'.$uid.$t];

}

//讀取用戶所屬用戶組

$groups=$this->getGroups($uid);

$ids= array();//保存用戶所屬用戶組設(shè)置的所有權(quán)限規(guī)則id

foreach($groupsas$g) {

$ids=array_merge($ids,explode(',',trim($g['rules'],',')));

}

$ids=array_unique($ids);

if(empty($ids)) {

$_authList[$uid.$t]= array();

return array();

}

$map=array(

'id'=>array('in',$ids),

'type'=>$type,

'status'=>0,

);

//讀取用戶組所有權(quán)限規(guī)則

$rules=Db::table($this->_config['AUTH_RULE'])->where($map)->field('condition,name,url')->select();

//循環(huán)規(guī)則,判斷結(jié)果。

$authList= array();//

foreach($rulesas$rule) {

if(!empty($rule['condition'])) {//根據(jù)condition進行驗證

$user=$this->getUserInfo($uid);//獲取用戶信息,一維數(shù)組

$command=preg_replace('/\{(\w*?)\}/','$user[\'\\1\']',$rule['condition']);

//dump($command);//debug

@(eval('$condition=('.$command.');'));

if($condition) {

$authList[]=strtolower($rule['url']);

}

}else{

//只要存在就記錄

$authList[]=strtolower($rule['url']);

}

}

$_authList[$uid.$t]=$authList;

if($this->_config['AUTH_TYPE']==2){

//規(guī)則列表結(jié)果保存到session

$_SESSION['_AUTH_LIST_'.$uid.$t]=$authList;

}

returnarray_unique($authList);

}

/**

*獲得用戶資料,根據(jù)自己的情況讀取數(shù)據(jù)庫

*/

protected functiongetUserInfo($uid) {

static$userinfo=array();

if(!isset($userinfo[$uid])){

$userinfo[$uid]=Db::table($this->_config['AUTH_USER'])->where(['id'=>$uid])->find();

}

return$userinfo[$uid];

}

}

3.登錄時使用

public function login(){

$uid=1;? //登錄后的用戶id

vendor("Auth"); //因為是將認證類作為自己的第三方包寫的,所以使用時需要先導(dǎo)入

$auth= newAuth();

$name=Request::instance()->controller().'/'.Request::instance()->action(); //如需要驗證Index/index 登錄的用戶是否有操作該類的權(quán)限

$res=$auth->check($name,$uid);? //調(diào)用驗證方法里的驗證

if(!$res){

echo'你沒有權(quán)限';

}else{

echo'登錄成功';

}

}

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

  • Spring Cloud為開發(fā)人員提供了快速構(gòu)建分布式系統(tǒng)中一些常見模式的工具(例如配置管理,服務(wù)發(fā)現(xiàn),斷路器,智...
    卡卡羅2017閱讀 136,578評論 19 139
  • NAME dnsmasq - A lightweight DHCP and caching DNS server....
    ximitc閱讀 2,993評論 0 0
  • auth類在thinkphp類庫里是原本就有的,thinkphp5里沒了,這里是將其修改為thinkphp5適用a...
    金星show閱讀 1,793評論 -1 3
  • 1. Java基礎(chǔ)部分 基礎(chǔ)部分的順序:基本語法,類相關(guān)的語法,內(nèi)部類的語法,繼承相關(guān)的語法,異常的語法,線程的語...
    子非魚_t_閱讀 34,734評論 18 399
  • 昨天下午,因為朋友的引薦,認識了在澳洲生活的Angela 她言簡意賅的跟我表明,自己現(xiàn)在是一個全職主婦,想要學(xué)習(xí)公...
    新洲十一街閱讀 1,165評論 2 15

友情鏈接更多精彩內(nèi)容