本文實(shí)例講述了Laravel5權(quán)限管理的實(shí)作方法。分享給大家參考,具體如下:
關(guān)於權(quán)限管理的思考
最近用laravel設(shè)計(jì)後臺(tái),後臺(tái)需要有個(gè)權(quán)限管理。權(quán)限管理實(shí)質(zhì)上分為兩個(gè)部分,首先是認(rèn)證,然後是權(quán)限。認(rèn)證部分非常好做,就是管理員登錄,記錄session。這個(gè)laravel中也有自備Auth來實(shí)現(xiàn)這個(gè)。最麻煩就是權(quán)限認(rèn)證。
權(quán)限認(rèn)證本質(zhì)上就是誰有權(quán)限管理什麼東西。這裡有兩個(gè)方面的維度,誰,就是用戶維度,在用戶維度,權(quán)限管理的粒度可以是用戶一個(gè)人,也可以是將用戶分組,如果將用戶分組,則涉及到的邏輯是一個(gè)用戶可以在多個(gè)組裡面嗎?在另一方面,管理什麼東西,這個(gè)東西是物的維度,一個(gè)頁面是一個(gè)東西,一個(gè)頁面上的一個(gè)元素也是一個(gè)東西,或者往大了說,一個(gè)功能是一個(gè)東西。所以做權(quán)限管理最重要的是確認(rèn)這兩個(gè)維度的粒度。這已經(jīng)不是技術(shù)的事情了,這個(gè)是需要需求討論的了。
基於上面的思考,我這次想做的權(quán)限管理,在使用者維度,是基於個(gè)人的。就是每個(gè)人的權(quán)限不一樣。在東西的維度,我設(shè)定路由為最小的單位,也就是可以為單一路由設(shè)定權(quán)限管理。
下面的思考就是使用什麼來標(biāo)記權(quán)限,可以使用位,也可以使用字符,也可以使用整型。後來我選擇了字符,基於兩點(diǎn)考慮:1 字符淺顯易懂,在數(shù)據(jù)庫(kù)中查找也比較方便2 我沒有按照某個(gè)權(quán)限查找有這個(gè)權(quán)限的人的需求,即沒有反查需求,使用位,整型等都意義不大。
接下來考慮如何和laravel結(jié)合,既然要為每個(gè)路由設(shè)定存取權(quán)限,那麼我當(dāng)然希望能在laravel的route.php路由管理中配置。最好就是在Route::get的時(shí)候有個(gè)參數(shù)能設(shè)定permission。這樣做的好處是權(quán)限設(shè)定簡(jiǎn)易了。在決定路由的時(shí)候,就順手寫了權(quán)限控制。壞處呢,也很明顯,laravel路由的三種方式只能寫一種了。就是Route::(method)這樣的方式了。
基本上決定好了就開乾。
路由設(shè)計(jì)
基本的路由是這樣的
Route::post('/admin/validate', ['uses' => 'AdminController@postValidate', 'permissions'=>['admin.validate', 'admin.index']]);
這裡在基本的製定路由action之後設(shè)定了一個(gè)permissions的屬性,這個(gè)屬性設(shè)計(jì)成數(shù)組,因?yàn)槔缫粋€(gè)post請(qǐng)求,它可能在某個(gè)頁面會(huì)觸發(fā),也可能在另一個(gè)頁面觸發(fā),那麼這個(gè)post請(qǐng)求就需要同時(shí)擁有兩個(gè)頁面路由的權(quán)限。
這裡使用admin.validate的權(quán)限控制,這樣,可以將權(quán)限分組,admin都是關(guān)於admin相關(guān)的分組,在資料庫(kù)中,我就會(huì)儲(chǔ)存一個(gè)二維數(shù)組,[admin] => ['validate', 'index']; 儲(chǔ)存成二維數(shù)組而不是一維的好處呢,一般後臺(tái)展示是有兩個(gè)維度的,一個(gè)是頭部的tab欄,一個(gè)是左邊的nav欄,就是說這個(gè)二維的數(shù)組和後臺(tái)的tab,nav欄是一一對(duì)應(yīng)的。
中間件設(shè)計(jì)
好了,下面我們就掛上中間件,並且設(shè)定所有的路由都走這個(gè)中間件
<?php namespace App\Http\Middleware; use Illuminate\Support\Facades\Session; use Closure; class Permission { /** * Handle an incoming request. * * @param \Illuminate\Http\Request $request * @param \Closure $next * @return mixed */ public function handle($request, Closure $next) { $permits = $this->getPermission($request); $admin = \App\Http\Middleware\Authenticate::getAuthUser(); // 只要有一個(gè)有權(quán)限,就可以進(jìn)入這個(gè)請(qǐng)求 foreach ($permits as $permit) { if ($permit == '*') { return $next($request); } if ($admin->hasPermission($permit)) { return $next($request); } } echo "沒有權(quán)限,請(qǐng)聯(lián)系管理員";exit; } // 獲取當(dāng)前路由需要的權(quán)限 public function getPermission($request) { $actions = $request->route()->getAction(); if (empty($actions['permissions'])) { echo "路由沒有設(shè)置權(quán)限";exit; } return $actions['permissions']; } }
這裡最關(guān)鍵的就getPermission函數(shù),從$request->route()->getAction ()來取得這個(gè)路由的action定義,然後從其中的permissions欄位中取得route.php定義的路由權(quán)限。
然後上面的middleware有個(gè):
admin?>hasPermission(admin?>hasPermission(permit);
這個(gè)就牽涉到??model的設(shè)計(jì)。
model設(shè)計(jì)
<?php namespace App\Models\Admin; use App\Models\Model as BaseModel; class Admin extends BaseModel { protected $table = 'admin'; // 判斷是否有某個(gè)權(quán)限 public function hasPermission($permission) { $permission_db = $this->permissions; if(in_array($permission, $permission_db)) { return true; } return false; } // permission 是一個(gè)二維數(shù)組 public function getPermissionsAttribute($value) { if (empty($value)) { return []; } $data = json_decode($value, true); $ret = []; foreach ($data as $key => $value) { $ret[] = $key; foreach ($value as $value2) { $ret[] = "{$key}.{$value2}"; } } return array_unique($ret); } // 全局設(shè)置permission public function setPermissionsAttribute($value) { $ret = []; foreach ($value as $item) { $keys = explode('.', $item); if (count($keys) != 2) { continue; } $ret[$keys[0]][] = $keys[1]; } $this->attributes['permissions'] = json_encode($ret); } }
在資料庫(kù)中,我將二維數(shù)組儲(chǔ)存為json,利用laravel的Attribute的get和set方法,完成了資料庫(kù)中json和外界程式邏輯的連接。然後hasPermission就顯得很輕鬆了,直接判斷in_array就ok了。
後續(xù)
這個(gè)權(quán)限認(rèn)證的邏輯就清晰了。然後如果頁面中某個(gè)tab或nav需要對(duì)不同權(quán)限的使用者展示,只需要在view中判斷
@if ($admin->hasPermission('admin.index')) @endif
就可以判斷這個(gè)使用者是否可以看到這個(gè)tab了。
總結(jié)
這個(gè)是一個(gè)不算複雜的用戶權(quán)限實(shí)現(xiàn),但是我感覺已經(jīng)能滿足大部分的後臺(tái)需求了。當(dāng)然可以最佳化的點(diǎn)可能很多,
例如permission是不是可以支援正規(guī),hasPermission如果儲(chǔ)存在nosql或pg中,是不是不用進(jìn)行json的資料解析,直接一個(gè)DB請(qǐng)求就能判斷是否有permission之類的?
希望本文所述對(duì)大家基於Laravel框架的PHP程式設(shè)計(jì)有所幫助。
更多Laravel5權(quán)限管理方法詳解相關(guān)文章請(qǐng)關(guān)注PHP中文網(wǎng)!

熱AI工具

Undress AI Tool
免費(fèi)脫衣圖片

Undresser.AI Undress
人工智慧驅(qū)動(dòng)的應(yīng)用程序,用於創(chuàng)建逼真的裸體照片

AI Clothes Remover
用於從照片中去除衣服的線上人工智慧工具。

Clothoff.io
AI脫衣器

Video Face Swap
使用我們完全免費(fèi)的人工智慧換臉工具,輕鬆在任何影片中換臉!

熱門文章

熱工具

記事本++7.3.1
好用且免費(fèi)的程式碼編輯器

SublimeText3漢化版
中文版,非常好用

禪工作室 13.0.1
強(qiáng)大的PHP整合開發(fā)環(huán)境

Dreamweaver CS6
視覺化網(wǎng)頁開發(fā)工具

SublimeText3 Mac版
神級(jí)程式碼編輯軟體(SublimeText3)