Laravel路由中用Spatie权限包实现OR逻辑权限校验的问题
解决Laravel中Spatie权限包路由层面的OR逻辑校验问题
一、快速实现:利用Spatie内置的OR语法
Spatie的permission中间件本身支持用|分隔多个权限,实现OR逻辑(满足任意一个权限即可访问),无需额外自定义中间件。
1. 路由组中使用
直接在permission中间件参数里用|拼接权限:
Route::group(['middleware' => ['auth:sanctum', 'verified', 'permission:provider_data|staff_data']], function () { Route::post('/Reports/getallhl7_reports', [ReportsController::class, 'getallhl7_reports'])->name('getallhl7_reports'); });
2. 单个路由中使用
给单个路由附加middleware即可,如需OR逻辑同样用|拼接:
// 单权限校验 Route::post('emailReport', [UtilitiesController::class, 'emailReport']) ->name('emailReport') ->middleware(['auth:sanctum', 'verified', 'permission:你的目标权限']); // 多权限OR校验 Route::post('emailReport', [UtilitiesController::class, 'emailReport']) ->name('emailReport') ->middleware(['auth:sanctum', 'verified', 'permission:permission_a|permission_b']);
二、自定义中间件实现复杂逻辑
如果需要更灵活的权限校验(比如权限+角色的组合OR、多组权限判断),可以自定义中间件:
1. 生成中间件
执行Artisan命令生成自定义中间件:
php artisan make:middleware CheckAnyPermission
2. 编写中间件逻辑
打开app/Http/Middleware/CheckAnyPermission.php,修改handle方法:
<?php namespace App\Http\Middleware; use Closure; use Illuminate\Http\Request; use Illuminate\Support\Facades\Auth; class CheckAnyPermission { public function handle(Request $request, Closure $next, ...$permissions) { // 确保用户已认证 $user = Auth::user(); if (!$user) { abort(401, '请先登录'); } // 遍历权限,满足任意一个则放行 foreach ($permissions as $permission) { if ($user->can($permission)) { return $next($request); } } // 无权限时返回403 abort(403, '无访问权限'); } }
3. 注册中间件
打开app/Http/Kernel.php,在$routeMiddleware数组中添加自定义中间件的别名:
protected $routeMiddleware = [ // ... 其他中间件 'permission.any' => \App\Http\Middleware\CheckAnyPermission::class, ];
4. 路由中使用自定义中间件
路由组或单个路由都可以用,参数用逗号分隔多个权限:
// 路由组示例 Route::group(['middleware' => ['auth:sanctum', 'verified', 'permission.any:provider_data,staff_data']], function () { Route::post('/Reports/getallhl7_reports', [ReportsController::class, 'getallhl7_reports'])->name('getallhl7_reports'); }); // 单个路由示例 Route::post('emailReport', [UtilitiesController::class, 'emailReport']) ->name('emailReport') ->middleware(['auth:sanctum', 'verified', 'permission.any:permission_x,permission_y']);
三、注意事项
- 确保User模型正确引入Spatie Trait:你的
User模型必须使用Spatie\Permission\Traits\HasRolestrait,否则Auth::user()不会有can()等权限相关方法:
use Spatie\Permission\Traits\HasRoles; class User extends Authenticatable { use HasRoles; // ... 其他代码 }
- 中间件顺序:
auth:sanctum必须放在权限中间件之前,只有先完成认证,才能获取到当前用户进行权限校验。
内容的提问来源于stack exchange,提问作者SScotti
相关产品推荐
相关产品推荐

