介紹如何在 Laravel 網頁專案中使用 Gates 功能,實做使用者角色與權限分級,區分一般使用者與管理者。
建立基本 Laravel 專案
首先參考 Laravel 6 建立含有使用者註冊、登入認證功能的網頁專案教學,建立好基本的 Laravel 專案,但不要執行 migrate。
使用者角色
假設我們希望將使用者區分為一般使用者(user)、一般管理者(manager)與系統管理者(admin)三類,分別授予不同的權限。
編輯 app/User.php,加入三種帳號角色名稱的常數字串,並將 role 這個欄位加入 fillable 中:
<?php
class User extends Authenticatable
{
// ...
const ROLE_ADMIN = 'admin';
const ROLE_MANAGER = 'manager';
const ROLE_USER = 'user';
protected $fillable = [
'name', 'email', 'password', 'role',
];
// ...
}
?>
資料庫 Migration
編輯 database/migrations/2014_10_12_000000_create_users_table.php 這一個建立使用者資料表的 migration 設定檔,在其中加入一欄用於儲存帳號角色的 role 欄位:
<?php
use App\User;
class CreateUsersTable extends Migration
{
// ...
public function up()
{
Schema::create('users', function (Blueprint $table) {
$table->bigIncrements('id');
$table->string('name');
$table->string('role')->default(User::ROLE_USER); // 加入角色欄位
$table->string('email')->unique();
$table->timestamp('email_verified_at')->nullable();
$table->string('password');
$table->rememberToken();
$table->timestamps();
});
}
}
?>
修改好之後,回到 Laravel 專案目錄,執行 migrate:
# 建立資料庫結構
php artisan migrate
使用者註冊 Controller
編輯 app/Http/Controllers/Auth/RegisterController.php,設定使用者註冊時的角色都是一般使用者:
<?php
protected function create(array $data)
{
return User::create([
'name' => $data['name'],
'email' => $data['email'],
'password' => Hash::make($data['password']),
'role' => User::ROLE_USER, // 預設為一般使用者
]);
}
?>
建立 Gate 權限規則
建立自訂的 Gate 權限規則,以判斷每位使用者是否有權限執行特定的動作。
編輯 app/Providers/AuthServiceProvider.php,加入自訂的 Gates 規則:
<?php
use App\User;
class AuthServiceProvider extends ServiceProvider
{
// ..
public function boot()
{
$this->registerPolicies();
// 系統管理者 Gate 規則
Gate::define('admin', function ($user) {
return $user->role === User::ROLE_ADMIN;
});
// 一般管理者 Gate 規則
Gate::define('manager', function ($user) {
return $user->role === User::ROLE_MANAGER;
});
// 一般使用者 Gate 規則
Gate::define('user', function ($user) {
return $user->role === User::ROLE_USER;
});
}
}
?>
這樣三種角色的基本權限就設定完成了,接下來就可以在 Laravel 專案的各種地方運用這些權限設定。
Blade 運用 Gate 權限設定
在 Blade 樣板中可以運用 @can、@cannot 或 @canany 來判斷使用者的權限(詳細用法可參考 Laravel 的文件):
@can('admin')
<!-- 系統管理者 -->
@elsecan('manager')
<!-- 一般管理者 -->
@else
<!-- 一般使用者 -->
@endcan
Controller 運用 Gate 權限設定
若在 Controller 中則可使用 Gate::allows 或 Gate::denies 判斷使用者權限:
<?php
use Illuminate\Support\Facades\Gate;
class Controller extends BaseController
{
// ...
public function someAction()
{
if (Gate::allows('admin')) {
return '系統管理者。';
}
if (Gate::denies('admin')) {
return '非系統管理者!';
}
}
}
?>
另外一種方式是運用 authorize 直接限制整個函數的執行權限:
<?php
class Controller extends BaseController
{
// ...
// 只有系統管理者可以執行
public function adminAction()
{
$this->authorize('admin');
// ...
}
}
?>
Middleware 運用 Gate 權限設定
在 Middleware 中也可以使用 Gate 的權限設定,例如應用在 Route 之中:
<?php
// 只有系統管理者可以執行
Route::get('/someAction', 'MyController@someAction') -> middleware('can:admin');
?>
設定帳號權限
在這裡的實作中,帳號的權限是根據 role 欄位值所決定的,要更改帳號權限的話,可以直接從資庫中更改,或是透過 Laravel 的 Tinker 環境快速設定:
# 進入 Tinker 互動式指令環境
php artisan tinker
然後在 Tinker 環境中,以一般的 PHP 語法直接更改使用者的 role 屬性:
<?php
# 將 demo@gmail.com 帳號設為系統管理者
use App\User;
User::where('email', 'demo@gmail.com') -> update(['role' => User::ROLE_ADMIN]);
?>
若需要讓系統管理者有網頁介面可以設定帳號權限,可參考上面這個 PHP 語法,自己設計修改帳號的使用者介面。
