天天看點

php laravel 權限,laravel實作簡單使用者權限的示例代碼

關于權限管理的思考

最近用laravel設計背景,背景需要有個權限管理。權限管理實質上分為兩個部分,首先是認證,然後是權限。認證部分非常好做,就是管理者登入,記錄session。這個laravel中也有自帶Auth來實作這個。最麻煩就是權限認證。

權限認證本質上就是誰有權限管理什麼東西。這裡有兩個方面的次元,誰,就是使用者次元,在使用者次元,權限管理的粒度可以是使用者一個人,也可以是将使用者分組,如果将使用者分組,則涉及到的邏輯是一個使用者可以在多個組裡面嗎?在另外一方面,管理什麼東西,這個東西是物的次元,一個頁面是一個東西,一個頁面上的一個元素也是一個東西,或者往大了說,一個功能是一個東西。是以做權限管理最重要的是确認這兩個次元的粒度。這個已經不是技術的事情了,這個是需要需求讨論的了。

基于上面的思考,我這次想做的權限管理,在使用者次元,是基于個人的。就是每個人的權限不一樣。在東西的次元,我設定路由為最小的機關,即可以為單個路由設定權限管理。

下面的思考就是使用什麼來标記權限,可以使用位,也可以使用字元,也可以使用整型。後來我選擇了字元,基于兩點考慮:1 字元淺顯易懂,在資料庫中查找也比較友善 2 我沒有按照某個權限查找有這個權限的人的需求,即沒有反查需求,使用位,整型等都意義不大。

接下來考慮如何和laravel結合,既然要為每個路由設定通路權限,那麼我當然希望能在laravel的route.php路由管理中配置。最好就是在Route::get的時候有個參數能設定permission。這樣做的好處是權限設定簡易了。在決定路由的時候,就順手寫了權限控制。壞處呢,也很明顯,laravel路由的三種方式隻能寫一種了。就是Route::(method)這樣的方式了。

基本決定好了就開幹。

路由設計

基本的路由是這樣的

Route::post('/admin/validate', ['uses' => '[email protected]', 'permissions'=>['admin.validate', 'admin.index']]);

這裡在基本的制定路由action之後設定了一個permissions的屬性,這個屬性設計成數組,因為比如一個post請求,它可能在某個頁面會觸發,也可能在另外一個頁面觸發,那麼這個post請求就需要同時擁有兩個頁面路由的權限。

這裡使用admin.validate的權限控制,這樣,可以将權限分組,admin都是關于admin相關的分組,在資料庫中,我就會存儲一個二維數組,[admin] => ['validate', 'index']; 存儲成二維數組而不是一維的好處呢,一般背景展示是有兩個次元的,一個是頭部的tab欄,一個是左邊的nav欄,就是說這個二維的數組和背景的tab,nav欄是一一對應的。

中間件設計

好了,下面我們就挂上中間件,并且設定所有的路由都走這個中間件

use Illuminate\Support\Facades\Session;

use Closure;

class Permission {

public function handle($request, Closure $next)

{

$permits = $this->getPermission($request);

$admin = \App\Http\Middleware\Authenticate::getAuthUser();

// 隻要有一個有權限,就可以進入這個請求

foreach ($permits as $permit) {

if ($permit == '*') {

return $next($request);

}

if ($admin->hasPermission($permit)) {

return $next($request);

}

}

echo "沒有權限,請聯系管理者";exit;

}

// 擷取目前路由需要的權限

public function getPermission($request)

{

$actions = $request->route()->getAction();

if (empty($actions['permissions'])) {

echo "路由沒有設定權限";exit;

}

return $actions['permissions'];

}

}

這裡最關鍵的就getPermission函數,從$request->route()->getAction()來擷取出這個路由的action定義,然後從其中的permissions字段中擷取route.php中定義的路由權限。

然後上面的middleware有個admin−>hasPermission(permit); 這個就涉及到model的設計。

model設計

use App\Models\Model as BaseModel;

class Admin extends BaseModel {

protected $table = 'admin';

// 判斷是否有某個權限

public function hasPermission($permission)

{

$permission_db = $this->permissions;

if(in_array($permission, $permission_db)) {

return true;

}

return false;

}

// permission 是一個二維數組

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

}

// 全局設定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);

}

}

在資料庫中,我将二維數組存儲為json,利用laravel的Attribute的get和set方法,完成了資料庫中json和外界程式邏輯的連接配接。然後hasPermission就顯得很輕松了,直接判斷in_array就ok了。

後續

這個權限認證的邏輯就清晰了。然後如果頁面中某個tab或者nav需要對不同權限的使用者展示,隻需要在view中判斷

@if ($admin->hasPermission('admin.index'))

@endif

就可以判斷這個使用者是否可以看到這個tab了。

以上就是本文的全部内容,希望對大家的學習有所幫助,也希望大家多多支援腳本之家。