设计
设计权限表格时,可以考虑以下字段:
- id: 权限 ID,自增主键
- name: 权限名称,用于标识该权限
- slug: 权限标识符,唯一值,用于程序中进行权限校验
- description: 权限描述,用于说明该权限的作用
- created_at: 创建时间
- updated_at: 更新时间
你还可以考虑添加其他字段,如下: - type: 权限类型,用于区分不同类型的权限,如前台用户权限、后台管理权限等
- module: 权限所属模块,如用户管理、订单管理等
- url: 权限对应的 URL,用于前端菜单的权限控制
- parent_id: 父级权限 ID,用于建立权限之间的父子关系
具体需要添加哪些字段,还需要根据实际情况进行考虑。
同时,还需要设计一个用户与权限之间的关联表,用于记录用户拥有的权限。可以考虑以下字段:
- id: 关联 ID,自增主键
- user_id: 用户 ID,关联到用户表
- permission_id: 权限 ID,关联到权限表
- created_at: 创建时间
- updated_at: 更新时间
同样,你还可以添加其他字段,如下: - type: 权限类型,同上
- module: 权限所属模块,同上
以上只是建议的表结构,具体实现需要根据实际情况进行考虑和调整。
怎么才能检验是否有相关权限呢?
为了检验用户是否有权限访问某个资源,通常的做法是在用户登录时生成一个包含所有权限的 token,然后在用户每次请求时,将这个 token 发送给服务器进行验证。
具体实现可以使用 JSON Web Tokens(JWT)或其他的身份验证库来实现。在 Laravel 中,你可以使用 Laravel Passport 或者类似的库来进行身份验证和授权管理。这些库可以帮助你轻松地生成和验证 token,以及限制访问资源的权限。同时,Laravel 的路由系统也提供了方便的中间件,你可以使用它们来限制用户访问某些路由或资源。
中间件
这里是一个简单的示例代码,用于检查用户是否有访问某个路由的权限。这里假设你已经定义了一个名为 permissions
的权限表。
首先,你需要在路由定义时使用中间件来检查权限。下面是一个例子:
Route::get('/dashboard', function () {
// 返回用户的仪表盘
})->middleware('check-permission:dashboard');
上面的代码中,check-permission
是一个自定义的中间件名,dashboard
是你要检查的权限的名称。
然后,在 app/Http/Middleware/CheckPermission.php
文件中,定义一个名为 handle
的方法,用于检查权限:
namespace App\Http\Middleware;
use Closure;
use Illuminate\Support\Facades\Auth;
class CheckPermission
{
public function handle($request, Closure $next, $permissionName)
{
if (! Auth::check()) {
return redirect('/login');
}
$user = Auth::user();
// 检查用户是否有访问此权限的权限
if (! $user->hasPermission($permissionName)) {
abort(403, 'You do not have permission to access this resource.');
}
return $next($request);
}
}
上面的代码中,我们首先检查用户是否已经登录,如果没有登录则重定向到登录页面。然后,我们从 Auth::user()
中获取当前用户,并调用 hasPermission
方法来检查是否具有所需的权限。如果用户没有该权限,我们会抛出一个 403 异常。
最后,我们需要在 User
模型中定义一个 hasPermission
方法,用于检查用户是否具有指定的权限:
namespace App\Models;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Support\Facades\DB;
class User extends Model
{
public function hasPermission($permissionName)
{
$query = DB::table('permissions')
->join('role_permission', 'permissions.id', '=', 'role_permission.permission_id')
->join('user_role', 'role_permission.role_id', '=', 'user_role.role_id')
->where('user_role.user_id', '=', $this->id)
->where('permissions.name', '=', $permissionName);
return $query->exists();
}
}
上面的代码中,我们在 User
模型中定义了一个 hasPermission
方法,它会检查用户是否具有指定的权限。该方法通过将 permissions
、role_permission
和 user_role
表进行连接,并查询是否存在具有给定名称的权限。如果存在,该方法返回 true
,否则返回 false
。
注意,上面的代码仅供参考,具体实现可能因项目而异。
一个简单的权限管理表的 SQL 建表语句
CREATE TABLE `permissions` (
`id` bigint(20) unsigned NOT NULL AUTO_INCREMENT,
`name` varchar(255) COLLATE utf8mb4_unicode_ci NOT NULL,
`slug` varchar(255) COLLATE utf8mb4_unicode_ci NOT NULL,
`description` text COLLATE utf8mb4_unicode_ci DEFAULT NULL,
`created_at` timestamp NULL DEFAULT NULL,
`updated_at` timestamp NULL DEFAULT NULL,
PRIMARY KEY (`id`),
UNIQUE KEY `permissions_slug_unique` (`slug`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
该表包含了 id
、name
、slug
、description
、created_at
和 updated_at
六个字段。
其中 id
是主键,自增类型;name
是权限名称,varchar
类型;slug
是权限标识符,varchar
类型;description
是权限描述,text
类型;created_at
和 updated_at
分别是创建时间和更新时间,timestamp
类型。
slug
字段设置为 UNIQUE 索引,保证每个权限标识符唯一。
当然,根据实际需求,可能还需要添加其他的字段,如权限类型、父级权限等。
前端鉴权
后端返回内容
{
"routes": [
{
"name": "home",
"path": "/home",
"method": "GET",
"permissions": ["view_home"]
},
{
"name": "users",
"path": "/users",
"method": "GET",
"permissions": ["view_users"]
},
{
"name": "create_user",
"path": "/users/create",
"method": "POST",
"permissions": ["create_user"]
},
{
"name": "edit_user",
"path": "/users/:id/edit",
"method": "PUT",
"permissions": ["edit_user"]
}
],
"permissions": ["view_home", "view_users", "create_user", "edit_user"]
}
前端Vue代码
<template>
<div>
<button v-if="can('create_user')" @click="createUser">Create User</button>
<button v-if="can('edit_user')" @click="editUser">Edit User</button>
<router-view></router-view>
</div>
</template>
<script>
import axios from 'axios';
export default {
data() {
return {
permissions: [],
routes: [],
};
},
created() {
this.getPermissions();
},
methods: {
getPermissions() {
axios.get('/api/permissions').then((response) => {
this.permissions = response.data.permissions;
this.routes = response.data.routes;
});
},
can(permission) {
return this.permissions.includes(permission);
},
createUser() {
// TODO: handle create user logic
},
editUser() {
// TODO: handle edit user logic
},
},
};
</script>
在这个例子中,我们在created
钩子中发送了一个请求,获取所有的路由和权限。然后我们将这些信息保存在Vue组件的data
对象中。
我们在Vue组件中添加了一个can
方法,用于检查当前用户是否拥有特定的权限。我们可以在Vue模板中使用v-if
指令来根据权限来控制按钮的显示。
当用户单击“Create User”或“Edit User”按钮时,我们可以使用Vue方法来执行特定的操作。在这里,我们只是简单地添加了TODO注释,以说明这些方法需要添加其他逻辑来完成相应的任务。
这样,我们就可以在前端Vue应用程序中根据用户的权限来控制按钮的显示和操作的执行。