如何在Laravel中实现数据库定义权限与集中式授权控制
Laravel 动态数据库权限+集中授权实现方案
一、先搞定数据库结构与模型关联
先搭建权限、角色、用户的关联数据表:
permissions表:存储具体权限,字段包含id,name(权限名称,如"查看文章"),slug(权限唯一标识,如"view-posts",用于代码调用),descriptionroles表:存储角色,字段包含id,name,slug(如"admin", "editor")role_permission关联表:字段role_id,permission_iduser_role关联表:字段user_id,role_id
然后在模型中定义关联关系:
// app/Models/User.php public function roles() { return $this->belongsToMany(Role::class); } public function permissions() { return $this->hasManyThrough(Permission::class, Role::class); } // 检查用户是否拥有指定权限 public function hasPermission(string $slug) { // 可添加缓存逻辑提升查询性能,比如将用户权限缓存到Redis return $this->permissions()->where('slug', $slug)->exists(); } // app/Models/Role.php public function permissions() { return $this->belongsToMany(Permission::class); } // app/Models/Permission.php public function roles() { return $this->belongsToMany(Role::class); }
二、注册全局授权Gate
在 app/Providers/AuthServiceProvider.php 的 boot 方法中,注册通用权限检查Gate,实现权限逻辑的统一封装:
public function boot() { $this->registerPolicies(); // 注册全局权限检查Gate Gate::define('access', function ($user, $permissionSlug) { return $user->hasPermission($permissionSlug); }); }
三、集中授权:用路由中间件统一检查
这是实现集中授权的核心,将权限检查逻辑统一放在中间件,避免在控制器方法中分散编写:
- 创建权限检查中间件:
php artisan make:middleware CheckPermission
- 编写中间件逻辑:
// app/Http/Middleware/CheckPermission.php public function handle(Request $request, Closure $next, string $permissionSlug) { if (! Gate::allows('access', $permissionSlug)) { abort(403, '无权限访问'); } return $next($request); }
- 在
app/Http/Kernel.php中注册中间件别名:
protected $routeMiddleware = [ // ... 其他中间件 'permission' => \App\Http\Middleware\CheckPermission::class, ];
- 在路由中统一配置权限,实现集中管理:
// routes/web.php Route::prefix('admin')->group(function () { // 需要"view-posts"权限才能访问列表页 Route::get('/posts', [PostController::class, 'index'])->middleware('permission:view-posts'); // 需要"create-posts"权限才能创建文章 Route::post('/posts', [PostController::class, 'store'])->middleware('permission:create-posts'); });
四、进阶优化:支持多权限/角色检查
如果需要检查用户拥有多个权限中的任意一个,可扩展中间件逻辑:
// 修改CheckPermission的handle方法 public function handle(Request $request, Closure $next, ...$permissions) { foreach ($permissions as $permissionSlug) { if (Gate::allows('access', $permissionSlug)) { return $next($request); } } abort(403); } // 路由中使用多权限配置 Route::get('/dashboard', [DashboardController::class, 'index'])->middleware('permission:view-dashboard,view-statistics');
若需检查角色,可参照上述逻辑创建CheckRole中间件,实现角色维度的集中授权。
五、控制器层面的集中授权
如果某个控制器下的所有方法都需要统一权限,可在控制器构造函数中批量设置:
// app/Http/Controllers/PostController.php public function __construct() { // 所有方法默认需要"manage-posts"权限 $this->middleware('permission:manage-posts'); // 指定部分方法无需权限检查 $this->middleware('permission:manage-posts')->except(['index']); }
通过这套方案,权限定义存储在数据库中动态维护,授权检查逻辑集中在中间件与Gate中,路由/控制器统一配置权限标识,完全避免授权代码分散的问题。
内容的提问来源于stack exchange,提问作者Mustafa Bayram
相关产品推荐
相关产品推荐

