本文将讲解如何使用 Laravel APIs 作为后端和 React.js 作为前端(分离的应用程序)实现细粒度权限系统。
由于前端与后端分离并通过 APIs 连接,我们将不会使用 Laravel blade 视图作为常规方式。
介绍
在许多 Web 应用程序中,我们都有一个角色和权限系统。每个用户都有一个角色,每个角色都有自己的权限,然后每个权限用于授权我们应用程序中的特定功能,如下图所示:
图片来源:sukanyasen.medium.com
那么,什么是细粒度权限 🤔?
通常,细粒度权限是指系统授予你的特权,允许你根据某些要求构建特定于网站的角色。- 来源
通过细粒度权限,你可以在同一视图中根据用户被授予的权限有不同的内容。
例如,
我们有一个应用程序有两个用户:
图片来源:sukanyasen.medium.com
如上图所示,
- 具有管理员角色的用户拥有完全访问权限(所有权限)…因此,他可以访问、创建、更新、删除或评论帖子以及用户和其他部分。
- 具有编辑角色的用户只拥有有限的访问权限(有限权限)…他只能访问帖子视图并编辑它们。
因此,细粒度权限背后的想法是,我们可以根据系统设置的权限控制我们的视图,并根据用户授予的权限在视图中显示/隐藏特定功能。
后端
我们将在我创建的现有 Laravel 应用程序(后端 API)上工作,通过使用 Laravel Sanctum 实现身份验证。
此 API(Laravel 应用程序)仅包含两个模型:
- User 模型。
- Post 模型。
它们的控制器、资源、迁移、种子和路由都已准备好。
没有太复杂的东西!只有一个后端 API 来获取、创建、更新和删除帖子,以及使用 API 令牌进行身份验证。
现在,让我们写一些代码!
现在是时候动手写一些代码了🖐
在 Laravel 中,使用 @spatie/laravel-permissions 包实现这样的系统非常容易,它可以帮助我们以非常简单的方式轻松管理用户角色和权限。
让我们先在我们的应用程序中安装 laravel-permissions 包(你可以遵循官方文档):
composer require spatie/laravel-permission
然后我们需要发布(配置、迁移):
php artisan vendor:publish --provider="Spatie\Permission\PermissionServiceProvider" --tag="migrations"
php artisan vendor:publish --provider="Spatie\Permission\PermissionServiceProvider" --tag="config"
然后运行迁移:
php artisan migrate
现在,我们需要创建应用程序所需的所有权限,然后创建角色并为它们分配权限。然后将角色分配给特定用户,
让我们创建一个种子文件来执行此操作,运行以下命令:
php artisan make:seeder PermissionsSeeder
将创建一个种子类在 database/seeders/PermissionsSeeder.php,打开它并在 run 方法中编写种子代码。
你可以按照下面的代码:
解释上面的种子类:
- 首先,如果需要,重置缓存的角色和权限。
- 创建一个数组,其中包含我们应用程序中所有所需的权限,然后将它们存储在数据库中。
- 创建 2 个角色(管理员具有完全权限,编辑者仅具有两个或有限权限)。
- 最后一件事,将角色分配给用户。将 用户 1 分配为管理员和 用户 2 分配为编辑器。
然后,我们需要在 database/seeders/DatabaseSeeder.php 的 run 方法中调用 PermissionsSeeder.php 类,如下所示:
$this->call([
PermissionsSeeder::class,
]);
然后运行播种命令:
php artisan db:seed
现在我们有了我们的用户和他们的角色和权限设置 🤓 🎉
- 用户 1 作为管理员拥有所有权限
- 用户 2 作为编辑器只拥有 2 个权限。
剩下两个步骤,完成后端!
- 步骤 1 - 使用我们的应用程序 API 对给定资源授权用户操作(因为我们永远不信任客户端)。
- 步骤 2 - 身份验证时返回用户的权限,以便稍后在我们的前端中使用。## 步骤1
使用 Laravel,你可以通过两种主要方式(使用 Gates,Policies)对给定资源授权用户操作。请查看 官方文档。
在我的情况下,你需要根据你的情况来选择,我将使用 通过用户模型使用 Policies 授权 用户操作。
示例:
在我的 PostController.php 中,用户必须进行身份验证(登录)并被授权(具有访问帖子的权限)
以及其他控制器方法的授权。
步骤2
我有一个GET端点,它是(/auth/profile),用于通过请求中发送的访问令牌获取已认证用户的数据,然后响应用户的数据... 这很好,但我需要获取用户的角色和权限与返回的用户数据。
我正在使用 Laravel 资源 来转换响应数据,因此我创建了一个名为 UserResource.php 的用户资源。 然后在我的 AuthController.php 的 profile 方法中,我使用此资源返回已认证用户的数据,如下所示:
return response()->json([ ‘user’ => new UserResource(auth()->user())], 200);
我的当前 UserResponse.php
正如我之前所说,我需要添加用户的角色和用户的权限,因为我们将需要它们在前端。
因此,它将如下所示:
这就是后端的全部内容。 🤓 ✅
前端
首先,让我解释在我们的视图中使用权限以根据授予用户的权限显示/隐藏特定功能的常见方法。
常见方法是使用Laravel Blade Views..使用 Blade 指令(can、cannot、role、hasrole…等)非常容易。
例如:
但是在我们的情况下,我们使用 React.js 作为与 Laravel 分离的应用程序,通过 API 连接。因此,我们没有 Laravel Blade 指令进行授权!
这就是为什么在后端部分(步骤2)中,我们返回已认证用户和他的角色的所有权限。
让我解释
在我的 React 应用程序中,当用户使用 (/auth/sign-in) API 端点登录时,我使用 Cookies 存储登录令牌,而不是存储用户数据...因此,我需要在页面加载时获取已登录用户的数据,然后将其存储在状态管理(Redux、Context API 等)中。
那么如何获取已登录用户的数据?
使用 API 端点(/auth/profile)。
通过向 (/auth/profile) 发送带有 Cookies 中存储的 令牌 的 GET 请求,我们会得到以下响应:
我们将用户数据存储在我们的状态管理中(在我的情况下是 Context API),因此我们随后可以在应用程序的任何地方访问用户数据。
最后一步,我们可以实现自己的(can、cannot、hasrole…等)方法,以便我们可以使用它们授权特定功能,方式与 Laravel Blade 指令相同。
实现(can)方法的示例:
将此方法放置在获取用户数据的同一位置(在我的情况下是我的状态管理的 Auth 上下文),因为它需要用户数据(权限)进行检查。
然后我们只需在应用程序的任何地方导入(can)方法并将其用于以下方式:
这就是全部内容,我们完成了!
你可以使用 Vue.js/Angular.js/Svelte.js 等实现相同的方法,它不仅仅适用于 React.js。这只是使用 API 与与 Laravel 分离的前端应用程序的示例。
高级
此后,你可以构建一个控制并(创建/更新/删除)角色及其权限并轻松将角色分配给用户的仪表板,如下所示:
在仪表板中更新角色
通过创建一个端点来获取按部分(产品、帖子...)分组的角色权限,然后在更新时使用同步将权限同步到角色中,如下所示:
$role->syncPermissions($request->permissions);
等等。
GitHub - munafio/laravel-granular-permissions: The Backend API using Laravel for the tutorial…
后端源代码
别忘了查看我的GitHub账户,并在Twitter上关注我😁❤️
译自:https://blog.munafio.com/granular-permissions-with-laravel-apis-react-frontend-f5697441bb5
评论(0)