0

Hướng dẫn phân quyền vào ENV trong project Laravel

hướng dẫn chi tiết từ lúc khởi tạo project đến khi hoàn thiện hệ thống phân quyền backend trong Laravel, sử dụng cấu hình file .env để cấp toàn quyền (Super Admin) cho một số user nhất định.

Phương pháp này sử dụng Laravel Gates (Gate::before). Bất cứ email nào được khai báo trong .env sẽ tự động bypass mọi kiểm tra quyền trong hệ thống.

Bước 1: Khởi tạo Project Laravel

Mở terminal và chạy lệnh sau để tạo một project Laravel mới:

Bash

composer create-project laravel/laravel admin-setup
cd admin-setup

Bước 2: Cấu hình file .env và Database

Mở file .env ở thư mục gốc của project. Bạn cần cấu hình kết nối database và thêm một biến môi trường mới để chứa danh sách email của các user có toàn quyền.

Đoạn mã

# Cấu hình Database
DB_CONNECTION=mysql
DB_HOST=127.0.0.1
DB_PORT=3306
DB_DATABASE=laravel_admin_db
DB_USERNAME=root
DB_PASSWORD=

# Danh sách email có Full Quyền (cách nhau bằng dấu phẩy)
SUPER_ADMIN_EMAILS="admin@yourdomain.com,ceo@yourdomain.com"

Lưu ý: Tạo database laravel_admin_db trong MySQL của bạn trước khi chạy bước tiếp theo.

Bước 3: Đăng ký biến môi trường vào Config

Trong Laravel, không nên gọi hàm env() trực tiếp ở mọi nơi ngoài file config. Hãy map biến này vào một file config.

Mở file config/auth.php và thêm đoạn sau vào cuối mảng return:

PHP

    // ... các cấu hình auth khác

    /*
    |--------------------------------------------------------------------------
    | Super Admins
    |--------------------------------------------------------------------------
    */
    'super_admins' => explode(',', env('SUPER_ADMIN_EMAILS', '')),

Bước 4: Chạy Migration cho bảng Users

Mặc định Laravel đã có sẵn migration cho bảng users. Chạy lệnh sau để tạo các bảng trong database:

Bash

php artisan migrate

Bước 5: Thiết lập Gate cấp toàn quyền (Quyền lực tối cao)

Tính năng Gate::before của Laravel cho phép chạy một logic kiểm tra trước bất kỳ quyền nào khác. Nếu callback trả về true, user đó sẽ được phép làm mọi thứ.

Mở file app/Providers/AppServiceProvider.php và cập nhật hàm boot:

PHP

namespace App\Providers;

use Illuminate\Support\ServiceProvider;
use Illuminate\Support\Facades\Gate;
use App\Models\User;

class AppServiceProvider extends ServiceProvider
{
    public function register(): void
    {
        //
    }

    public function boot(): void
    {
        // Kiểm tra xem email của user có nằm trong danh sách .env không
        Gate::before(function (User $user, string $ability) {
            $superAdmins = config('auth.super_admins');

            if (in_array($user->email, $superAdmins)) {
                return true; // Cấp toàn quyền
            }
            
            // Trả về null để Laravel tiếp tục kiểm tra các Policy/Gate khác (nếu có)
            return null; 
        });
    }
}

Bước 6: Tạo Middleware để bảo vệ Route Backend (Tùy chọn)

Mặc dù Gate giúp xử lý logic phân quyền (Authorization), bạn thường cần một Middleware để chặn người dùng không có quyền truy cập vào các route của khu vực quản trị.

Chạy lệnh tạo Middleware:

Bash

php artisan make:middleware SuperAdminMiddleware

Mở file app/Http/Middleware/SuperAdminMiddleware.php:

PHP

namespace App\Http\Middleware;

use Closure;
use Illuminate\Http\Request;
use Symfony\Component\HttpFoundation\Response;

class SuperAdminMiddleware
{
    public function handle(Request $request, Closure $next): Response
    {
        // Nếu user chưa đăng nhập
        if (!auth()->check()) {
            abort(401, 'Vui lòng đăng nhập.');
        }

        // Kiểm tra xem email có trong danh sách super_admins config không
        if (!in_array(auth()->user()->email, config('auth.super_admins'))) {
            abort(403, 'Bạn không có quyền truy cập khu vực này.');
        }

        return $next($request);
    }
}

Đăng ký Middleware (với Laravel 11+, cấu hình trong bootstrap/app.php):

PHP

use App\Http\Middleware\SuperAdminMiddleware;

->withMiddleware(function (Middleware $middleware) {
    $middleware->alias([
        'super.admin' => SuperAdminMiddleware::class,
    ]);
})

Bước 7: Tạo Seeder khởi tạo User test

Để test hệ thống, chúng ta tạo một user có email trùng với email cấu hình trong .env và một user thường.

Bash

php artisan make:seeder UserSeeder

Mở database/seeders/UserSeeder.php:

PHP

namespace Database\Seeders;

use Illuminate\Database\Seeder;
use App\Models\User;
use Illuminate\Support\Facades\Hash;

class UserSeeder extends Seeder
{
    public function run(): void
    {
        // User có full quyền (Vì email khớp với .env)
        User::create([
            'name' => 'Super Admin',
            'email' => 'admin@yourdomain.com',
            'password' => Hash::make('password123'),
        ]);

        // User thường
        User::create([
            'name' => 'Normal User',
            'email' => 'user@yourdomain.com',
            'password' => Hash::make('password123'),
        ]);
    }
}

Chạy seeder:

Bash

php artisan db:seed --class=UserSeeder

Bước 8: Thiết lập Route để kiểm tra

Mở routes/web.php và thêm các route sau để giả lập quá trình đăng nhập và test quyền:

PHP

use Illuminate\Support\Facades\Route;
use Illuminate\Support\Facades\Auth;

// Giả lập Đăng nhập bằng user ID
Route::get('/login-admin', function () {
    Auth::loginUsingId(1); // Đăng nhập user admin@yourdomain.com
    return "Đã đăng nhập tài khoản ADMIN. <a href='/admin/dashboard'>Vào Dashboard</a>";
});

Route::get('/login-user', function () {
    Auth::loginUsingId(2); // Đăng nhập user user@yourdomain.com
    return "Đã đăng nhập tài khoản THƯỜNG. <a href='/admin/dashboard'>Vào Dashboard</a>";
});

// Route được bảo vệ bởi middleware super.admin
Route::middleware(['auth', 'super.admin'])->prefix('admin')->group(function () {
    Route::get('/dashboard', function () {
        return "Chào mừng Super Admin! Bạn có quyền truy cập vào đây.";
    });
});

Bật server bằng php artisan serve. Bạn có thể truy cập /login-user, sau đó click vào link để xem lỗi 403 (bị chặn). Ngược lại, khi truy cập /login-admin, bạn sẽ vào được Dashboard bình thường. Ngoài ra, với Gate::before, tài khoản admin này sẽ tự động pass qua mọi hàm $user->can('edit-post') hay bất kỳ Policy nào bạn định nghĩa sau này.


All rights reserved

Viblo
Hãy đăng ký một tài khoản Viblo để nhận được nhiều bài viết thú vị hơn.
Đăng kí