простое и гибкое управление разрешениями пользователей

Авторизация Laravel и управление разрешениями ролей

простое руководство по гибкой аутентификации и авторизации

Во многих веб-проектах у нас есть разные роли пользователей, взаимодействующих с системой. У каждой роли есть собственное разрешение. Каждая функция системы может быть включена или отключена для этих ролей. Мы можем определить разрешения пользователей в наших кодах и проверить, имеют ли они право выполнять запрошенное действие или нет. Лучшим способом, в основном в более гибких системах, является создание системы управления ролями и авторизацией. Я объясню, как реализовать систему авторизации Laravel и определить права пользователей в зависимости от их ролей.

В этом посте мы сначала управляем пользователями в группах, которые мы назвали ролями. У каждой роли разные разрешения. Чтобы избежать конфликта разрешений, мы предполагаем, что у каждого пользователя есть только одна роль. Во-вторых, авторизация Laravel реализуется промежуточным программным обеспечением. Это промежуточное ПО проверяет разрешение роли пользователя и авторизует запросы пользователей.

Создание роли и разрешений

Чтобы реализовать авторизацию Laravel, мы создадим таблицу ролей и разрешений. Чтобы назначить роли для пользователей, мы создаем таблицу ролей. Миграция для таблицы ролей очень проста:

Schema::create(‘roles’, function (Blueprint $table) {
 $table->increments(‘id’);
 $table->string(‘name’);
 $table->string(‘description’)->nullable();
 $table->timestamps();
});

У нас есть идентификатор и имя для ролей. Все пользователи будут управляться в этих ролях. Также есть поле описания, потому что вам может понадобиться небольшая заметка о ролях, чтобы описать каждую роль для себя.

После этого мы добавляем внешний ключ role_id в пользовательскую таблицу. Добавление этого поля в модель пользователя по умолчанию помогает нам в авторизации Laravel.

$table->unsignedInteger(‘role_id’)->index();
$table->foreign(‘role_id’)->references(‘id’)->on(‘roles’);

Теперь поговорим о таблице разрешений. Каждый запрос приводит к методу контроллера. Таким образом, мы сохраняем список всех методов и имя их контроллера в таблице разрешений. Позже мы объясним, как мы собираем этот список и как мы проверяем авторизацию пользователей в Laravel с помощью этой таблицы разрешений.

Schema::create(‘permissions’, function (Blueprint $table) {
 $table->increments(‘id’);
 $table->string(‘name’)->nullable();
 $table->string(‘key’)->nullable();
 $table->string(‘controller’);
 $table->string(‘method’);
 $table->timestamps();
});

Наконец, между ролями и разрешениями создана связь.

Schema::create(‘permission_role’, function (Blueprint $table) {
 $table->unsignedInteger(‘permission_id’);
 $table->unsignedInteger(‘role_id’);
$table->foreign(‘permission_id’)
 ->references(‘id’)
 ->on(‘permissions’)
 ->onDelete(‘cascade’);
$table->foreign(‘role_id’)
 ->references(‘id’)
 ->on(‘roles’)
 ->onDelete(‘cascade’);
$table->primary([‘permission_id’, ‘role_id’]);
});

Мы создали полную архитектуру пользователей- ›ролей-› разрешений. После этого в этих таблицах будет храниться список доступа. Итак, мы можем легко реализовать авторизацию Laravel, сверяя запросы по этому списку.

Прочтите Документацию по миграции Laravel для получения дополнительной информации о создании таблиц.

Создание списка доступа для разрешений пользователя

Вся цель этого поста - быть динамичным. Особенно в системах с другим типом ролей. Нам нужно создать список разрешений в системе. Также этот список должен обновляться по мере развития системы. Список контроллеров и методов хорошо отображает все разрешения в системе. Каждый маршрут ведет к методу контроллера. Итак, неплохо составить список разрешений, используя список маршрутов.

Для этого я использовал сидер базы данных Laravel. Для начала напишем сеялку ролей. Он создает необходимые нам основные роли и сохраняет их в таблице ролей. Выполнение этой команды artisan создаст для вас RolesSeeder:

php artisan make:seeder RolesTableSeeder

Внутри этого RolesTableSeeder мы создаем наши основные роли:

DB::table(‘roles’)->insert([
 [‘name’ => ‘admin’],
 [‘name’ => ‘operator’],
 [‘name’ => ‘customer’],
]);

Вы можете добавить столько ролей, сколько вам нужно. Кроме того, вы можете создавать новые роли на своем веб-сайте, когда вам нужна новая.

Второй шаг - создать список авторизации для каждой роли. мы создаем еще один сидер Laravel, в котором заполняем таблицу разрешений:

php artisan make:seeder PermissionTableSeeder

Во-первых, мы получаем список всех маршрутов. Затем мы проверяем базу данных, если разрешение уже сохранено. После этого, если этого разрешения еще нет в таблице, мы вставляем новые разрешения в таблицу разрешений. Ведь мы привязываем все разрешения к роли админа.

$permission_ids = []; // an empty array of stored permission IDs
// iterate though all routes
foreach (Route::getRoutes()->getRoutes() as $key => $route)
{
 // get route action
 $action = $route->getActionname();
// separating controller and method
 $_action = explode(‘@’,$action);
 
 $controller = $_action[0];
 $method = end($_action);
 
 // check if this permission is already exists
 $permission_check = Permission::where(
         [‘controller’=>$controller,’method’=>$method]
     )->first();
 if(!$permission_check){
   $permission = new Permission;
   $permission->controller = $controller;
   $permission->method = $method;
   $permission->save();
   // add stored permission id in array
   $permission_ids[] = $permission->id;
 }
}
// find admin role.
$admin_role = Role::where(‘name’,’admin’)->first();
// atache all permissions to admin role
$admin_role->permissions()->attach($permission_ids);

Авторизация laravel с помощью программного обеспечения

Каждый запрос в Laravel проходит через промежуточное ПО. Зная, что создание промежуточного программного обеспечения RolesAuth выполнит авторизацию Laravel. Вы можете создать промежуточное ПО вручную или с помощью специальной команды:

php artisan make:middleware RolesAuth

Внутри этого промежуточного программного обеспечения мы получаем все разрешения для вошедшего в систему пользователя. Затем мы проверяем, есть ли запрошенное действие в списке разрешений. Если запрошенное действие не может быть найдено в списке разрешений, возвращается ответ с ошибкой 403.

// get user role permissions
$role = Role::findOrFail(auth()->user()->role_id);
$permissions = $role->permissions;
// get requested action
$actionName = class_basename($request->route()->getActionname());
// check if requested action is in permissions list
foreach ($permissions as $permission)
{
 $_namespaces_chunks = explode(‘\\’, $permission->controller);
 $controller = end($_namespaces_chunks);
 if ($actionName == $controller . ‘@’ . $permission->method)
 {
   // authorized request
   return $next($request);
 }
}
// none authorized request
return response(‘Unauthorized Action’, 403);

Наконец, вы можете зарегистрировать это промежуточное ПО в Laravel и использовать его в соответствии с вашими требованиями.

Я начал публиковать свой опыт разработки Laravel, здесь вы можете увидеть мой пост о локализации Laravel. Прокомментируйте свои вопросы об этом посте или любые другие вопросы о разработке Laravel в этой области.

Обновление 2020:
Теперь вы можете использовать мою сборку пакета разрешений Laravel на основе этой статьи. Он стал еще лучше, чище и проще для понимания.
https://github.com/amiryousefi/laravel-permission