權限設計是後臺管理很重要的一個功能,因此要好好設計。 PHP 已經有不少這方面的packages了,就不用咱們重複造輪子了。固然,若是你願意能夠從頭開始~php
之前作權限認證的方式有好幾種,我說說經常使用的兩種吧!laravel
packages
會提供用戶能夠直接擁有權限功能)模型關聯關係處理:git
<?php namespace App\Models; use Illuminate\Notifications\Notifiable; use Illuminate\Foundation\Auth\User as Authenticatable; class User extends Authenticatable { use Notifiable; /** * The attributes that should be hidden for arrays. * * @var array */ protected $hidden = [ 'password', 'remember_token', ]; // 用戶和角色的模型關聯關係 public function roles() { return $this->belongsToMany(Role::class); } /**************************************** * 封裝一個方法方便使用 * 1. 須要的權限 * 2. 遍歷當期那用戶擁有的全部角色 * 3. 再經過角色判斷是否有當前須要的權限 ****************************************/ public function hasPermission($permissionName) { foreach ($this->roles as $role) { if ($role->permisssions()->where('name', $permissionName)->exists()) { return true;; } } return false; } }
<?php namespace App\Models; class Role extends Model { // 用戶和角色的模型關聯關係 public function users() { return $this->belongsToMany(User::class); } // 角色和權限的模型關聯關係 public function permissions() { return $this->belongsToMany(Permission::class); } }
<?php namespace App\Models; class Role extends Model { // 角色和權限的模型關聯關係 public function roles() { return $this->belongsToMany(Role::class); } }
######################################## # users: +-------+---------+-----------+ | id | name | password | +-----------------+-----------+ | 1 | gps | 123456 | +-----------------+-----------+ | 2 | david | 123456 | +-----------------+-----------+ ######################################## # roles: +-------+---------+ | id | name | +-----------------+ | 1 | admin | +-----------------+ ######################################## # permissions: +-------+-----------------+ | id | name | +-------------------------+ | 1 | create_product | | 2 | delete_product | +-------------------------+ ######################################## # role_user (用戶 gps 擁有 admin 角色身份) +---------+---------+ | role_id | user_id | +---------+---------+ | 1 | 1 | +------------------+ ######################################## # permission_role (角色 admin 擁有建立商品和刪除商品的權限) +---------+---------------+ | role_id | permission_id | +---------+---------------+ | 1 | 1 | | 1 | 2 | +-------------------------+
第一種大概介紹一下:github
<?php namespace App\Http\Controllers; use App\Models\Product; class ProductsController extends Controller { public function store(Request $request) { // 判斷當前登陸的用戶是否有權限 if (! $request->user()->hasPermission('create_product')) { abort(403); } // do something return back()->with('status', '添加商品成功'); } public function destroy(Product $product) { // 判斷當前登陸的用戶是否有權限 if (! $request->user()->hasPermission('delete_product')) { abort(403); } // do something return back()->with('status', '刪除商品成功'); } }
經過上面的代碼咱們能夠看到,即便封裝了權限驗證的代碼,仍是要在不一樣的方法進行驗證,並且可擴展性不高,這時候咱們只須要在權限表加一個字段,就能夠解決問題數據庫
1. permissions (加多一個 route 字段, 若是不在 laravel 中使用,能夠加一個 url 字段匹配) +-------+------------------+------+-----+---------+----------------+ | Field | Type | Null | Key | Default | Extra | +-------+------------------+------+-----+---------+----------------+ | id | int(10) unsigned | NO | PRI | NULL | auto_increment | | name | varchar(191) | NO | | NULL | | | route | varchar(191) | NO | | NULL | | +-------+------------------+------+-----+---------+----------------+ 2. 這時候插入數據的時候,咱們只要作好相關的錄入 +-------+-----------------+------------------+ | id | name | route | +-------------------------+------------------+ | 1 | create_product | products.store | | 2 | delete_product | products.destroy | +-------------------------+------------------+
添加好數據的時候,咱們就不用再控制器裏驗證了,咱們只須要新建一箇中間件。this
<?php namespace App\Http\Middleware; use Closure; use Illuminate\Support\Facades\Route; use App\Models\Permission; class PermissionAuth { /** * 把這個中間件放入路由組,把須要的驗證的路由 * 放入這個中間組裏 */ public function handle($request, Closure $next) { /**************************************** * 獲取當前路由的別名,若是沒有返回 null * (不在 laravel 中使用時,能夠獲取當前 url) ****************************************/ $route = Route::currentRouteName(); // 判斷權限表中這條路由是否須要驗證 if ($permission = Permission::where('route', $route)->first()) { // 當前用戶不擁有這個權限的名字 if (! auth()->user()->hasPermission($permission->name)) { return response()->view('errors.403', ['status' => "權限不足,須要:{$permission->name}權限"]); } } return $next($request); } }
若是是在 laravel 中使用,已經有輪子了,請使用 https://github.com/spatie/laravel-permissionurl