thinkphp5 中的權(quán)限認(rè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ī)則表達(dá)式扫倡,為空表示存在就驗證谦秧,不為空表示按照條件驗',

`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='用戶組明細(xì)表';

用戶組表

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.認(rèn)證類

classAuth{

//默認(rèn)配置

protected$_config= array(

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

'AUTH_TYPE'=>1,//認(rèn)證方式,1為實時認(rèn)證撵溃;2為登錄認(rèn)證疚鲤。

'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認(rèn)證用戶的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進(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['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"); //因為是將認(rèn)證類作為自己的第三方包寫的,所以使用時需要先導(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)系作者
  • 序言:七十年代末语淘,一起剝皮案震驚了整個濱河市诲宇,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌惶翻,老刑警劉巖姑蓝,帶你破解...
    沈念sama閱讀 217,826評論 6 506
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異吕粗,居然都是意外死亡纺荧,警方通過查閱死者的電腦和手機,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,968評論 3 395
  • 文/潘曉璐 我一進(jìn)店門颅筋,熙熙樓的掌柜王于貴愁眉苦臉地迎上來宙暇,“玉大人,你說我怎么就攤上這事议泵≌计叮” “怎么了?”我有些...
    開封第一講書人閱讀 164,234評論 0 354
  • 文/不壞的土叔 我叫張陵先口,是天一觀的道長型奥。 經(jīng)常有香客問我,道長碉京,這世上最難降的妖魔是什么桩引? 我笑而不...
    開封第一講書人閱讀 58,562評論 1 293
  • 正文 為了忘掉前任,我火速辦了婚禮收夸,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘血崭。我一直安慰自己卧惜,他們只是感情好厘灼,可當(dāng)我...
    茶點故事閱讀 67,611評論 6 392
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著咽瓷,像睡著了一般设凹。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上茅姜,一...
    開封第一講書人閱讀 51,482評論 1 302
  • 那天闪朱,我揣著相機與錄音,去河邊找鬼钻洒。 笑死奋姿,一個胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的素标。 我是一名探鬼主播称诗,決...
    沈念sama閱讀 40,271評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼头遭!你這毒婦竟也來了寓免?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 39,166評論 0 276
  • 序言:老撾萬榮一對情侶失蹤计维,失蹤者是張志新(化名)和其女友劉穎袜香,沒想到半個月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體鲫惶,經(jīng)...
    沈念sama閱讀 45,608評論 1 314
  • 正文 獨居荒郊野嶺守林人離奇死亡蜈首,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,814評論 3 336
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了剑按。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片疾就。...
    茶點故事閱讀 39,926評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖艺蝴,靈堂內(nèi)的尸體忽然破棺而出猬腰,到底是詐尸還是另有隱情,我是刑警寧澤猜敢,帶...
    沈念sama閱讀 35,644評論 5 346
  • 正文 年R本政府宣布姑荷,位于F島的核電站,受9級特大地震影響缩擂,放射性物質(zhì)發(fā)生泄漏鼠冕。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 41,249評論 3 329
  • 文/蒙蒙 一胯盯、第九天 我趴在偏房一處隱蔽的房頂上張望懈费。 院中可真熱鬧,春花似錦博脑、人聲如沸憎乙。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,866評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽泞边。三九已至该押,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間阵谚,已是汗流浹背蚕礼。 一陣腳步聲響...
    開封第一講書人閱讀 32,991評論 1 269
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留梢什,地道東北人奠蹬。 一個月前我還...
    沈念sama閱讀 48,063評論 3 370
  • 正文 我出身青樓,卻偏偏與公主長得像绳矩,于是被迫代替她去往敵國和親罩润。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 44,871評論 2 354

推薦閱讀更多精彩內(nèi)容

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