首頁 > php教程 > PHP视频 > Laravel5權限管理方法詳解

Laravel5權限管理方法詳解

高洛峰
發布: 2016-12-23 17:27:10
原創
1440 人瀏覽過

本文實例講述了Laravel5權限管理的實作方法。分享給大家參考,具體如下:

關於權限管理的思考

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

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

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

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

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

基本上決定好了就開乾。

路由設計

基本的路由是這樣的

Route::post('/admin/validate', ['uses' => 'AdminController@postValidate', 'permissions'=>['admin.validate', 'admin.index']]);
登入後複製

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

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

中間件設計

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

<?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();
    // 只要有一个有权限,就可以进入这个请求
    foreach ($permits as $permit) {
      if ($permit == &#39;*&#39;) {
        return $next($request);
      }
      if ($admin->hasPermission($permit)) {
        return $next($request);
      }
    }
    echo "没有权限,请联系管理员";exit;
  }
  // 获取当前路由需要的权限
  public function getPermission($request)
  {
    $actions = $request->route()->getAction();
    if (empty($actions[&#39;permissions&#39;])) {
      echo "路由没有设置权限";exit;
    }
    return $actions[&#39;permissions&#39;];
  }
}
登入後複製

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

然後上面的middleware有個:

admin−>hasPermission(admin−>hasPermission(permit);
登入後複製

這個就牽涉到​​model的設計。

model設計

<?php namespace App\Models\Admin;
use App\Models\Model as BaseModel;
class Admin extends BaseModel {
  protected $table = &#39;admin&#39;;
  // 判断是否有某个权限
  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(&#39;.&#39;, $item);
      if (count($keys) != 2) {
        continue;
      }
      $ret[$keys[0]][] = $keys[1];
    }
    $this->attributes[&#39;permissions&#39;] = json_encode($ret);
  }
}
登入後複製

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

後續

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

@if ($admin->hasPermission(&#39;admin.index&#39;))
@endif
登入後複製

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

總結

這個是一個不算複雜的用戶權限實現,但是我感覺已經能滿足大部分的後台需求了。當然可以最佳化的點可能很多,
例如permission是不是可以支援正規,hasPermission如果儲存在nosql或pg中,是不是不用進行json的資料解析,直接一個DB請求就能判斷是否有permission之類的?

希望本文所述對大家基於Laravel框架的PHP程式設計有所幫助。

更多Laravel5權限管理方法詳解相關文章請關注PHP中文網!

相關標籤:
來源:php.cn
本網站聲明
本文內容由網友自願投稿,版權歸原作者所有。本站不承擔相應的法律責任。如發現涉嫌抄襲或侵權的內容,請聯絡admin@php.cn
熱門推薦
熱門教學
更多>
最新下載
更多>
網站特效
網站源碼
網站素材
前端模板