PHP

Laravel 6 使用 Gates 實做使用者角色、權限分級教學

介紹如何在 Laravel 網頁專案中使用 Gates 功能,實做使用者角色與權限分級,區分一般使用者與管理者。

建立基本 Laravel 專案

首先參考 Laravel 6 建立含有使用者註冊、登入認證功能的網頁專案教學,建立好基本的 Laravel 專案,但不要執行 migrate

使用者角色

假設我們希望將使用者區分為一般使用者(user)、一般管理者(manager)與系統管理者(admin)三類,分別授予不同的權限。

編輯 app/User.php,加入三種帳號角色名稱的常數字串,並將 role 這個欄位加入 fillable 中:

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 欄位:

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,設定使用者註冊時的角色都是一般使用者:

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 規則:

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::allowsGate::denies 判斷使用者權限:

use Illuminate\Support\Facades\Gate;

class Controller extends BaseController
{
    // ...

    public function someAction()
    {
        if (Gate::allows('admin')) {
            return '系統管理者。';
        }

        if (Gate::denies('admin')) {
            return '非系統管理者!';
        }
    }
}

另外一種方式是運用 authorize 直接限制整個函數的執行權限:

class Controller extends BaseController
{
    // ...

    // 只有系統管理者可以執行
    public function adminAction()
    {
        $this->authorize('admin');

        // ...
    }
}

Middleware 運用 Gate 權限設定

在 Middleware 中也可以使用 Gate 的權限設定,例如應用在 Route 之中:

// 只有系統管理者可以執行
Route::get('/someAction', 'MyController@someAction') -> middleware('can:admin');

設定帳號權限

在這裡的實作中,帳號的權限是根據 role 欄位值所決定的,要更改帳號權限的話,可以直接從資庫中更改,或是透過 Laravel 的 Tinker 環境快速設定:

# 進入 Tinker 互動式指令環境
php artisan tinker

然後在 Tinker 環境中,以一般的 PHP 語法直接更改使用者的 role 屬性:

# 將 demo@gmail.com 帳號設為系統管理者
use App\User;
User::where('email', 'demo@gmail.com') -> update(['role' => User::ROLE_ADMIN]);

若需要讓系統管理者有網頁介面可以設定帳號權限,可參考上面這個 PHP 語法,自己設計修改帳號的使用者介面。

Share
Published by
Office Guide
Tags: Laravel

Recent Posts

Python 使用 PyAutoGUI 自動操作滑鼠與鍵盤

本篇介紹如何在 Python ...

9 個月 ago

Ubuntu Linux 以 WireGuard 架設 VPN 伺服器教學與範例

本篇介紹如何在 Ubuntu ...

9 個月 ago

Linux 網路設定 ip 指令用法教學與範例

本篇介紹如何在 Linux 系...

9 個月 ago

Windows 使用 TPM 虛擬智慧卡保護 SSH 金鑰教學與範例

本篇介紹如何在 Windows...

10 個月 ago

Linux 以 Shamir’s Secret Sharing 分割保存金鑰教學與範例

介紹如何在 Linux 中使用...

10 個月 ago

Linux 以 Cryptsetup、LUKS 加密 USB 隨身碟教學與範例

介紹如何在 Linux 系統中...

10 個月 ago