必须使用spatie权限包并严格遵循五步流程:安装发布迁移、建模引入trait、tinker创建角色权限、编写带多参数校验的中间件、路由用数组语法传参,否则权限拦截必然失效。

要在Laravel 8中让不同角色的用户只能访问对应权限的路由,必须避开中间件硬编码角色逻辑、漏传参数、实时查库这三大高频失效点,否则即使写了中间件也完全不拦截请求。
安装并初始化Spatie权限包
执行composer require spatie/laravel-permission安装包,这是目前Laravel 8中最稳定的角色权限方案,支持数据库动态管理且兼容Gate机制。
运行php artisan vendor:publish --provider="Spatie\Permission\PermissionServiceProvider"发布迁移文件——【这一步不可跳过,否则roles、permissions等5张表不会创建,后续所有赋权操作都会静默失败】。
执行php artisan migrate完成数据库表建立。
在App\Models\User中引入并使用trait:use Spatie\Permission\Traits\HasRoles;,并在class定义内添加use HasRoles;。
创建角色与权限并绑定用户
进入Tinker:php artisan tinker,依次执行:
清空旧缓存:app()->make(\Spatie\Permission\PermissionRegistrar::class)->forgetCachedPermissions();
创建权限:Permission::create(['name' => 'manage dashboard']);
创建角色:$admin = Role::create(['name' => 'admin']);
将权限赋予角色:$admin->givePermissionTo('manage dashboard');
给用户分配角色:User::find(1)->assignRole('admin');——这一步后,用户即继承该角色全部权限,无需手动同步。
编写并注册角色校验中间件
用Artisan命令生成中间件:php artisan make:middleware CheckRole。
打开app/Http/Middleware/CheckRole.php,确认handle()方法签名完整:public function handle($request, Closure $next, $roles)——【若写成$role单参数,遇到role:admin|editor时无法explode拆分,权限判断必然失败】。
在handle方法中写入校验逻辑:
if (!$request->user() || !$request->user()->hasAnyRole(explode('|', $roles))) { abort(403); }
打开app/Http/Kernel.php,在$routeMiddleware数组中添加:'role' => \App\Http\Middleware\CheckRole::class,。
在路由中正确调用带参中间件
第一步:在routes/web.php中声明路由时,必须使用数组语法传参,例如:
Route::get('/admin/dashboard', [AdminController::class, 'index'])->middleware(['role:admin|editor']);
第二步:验证是否生效——访问该路由时,未登录用户会重定向到登录页;已登录但无admin或editor角色的用户将直接返回403错误页面。
第三步:检查常见错误:如果路由加了->middleware('role:admin')却没拦截,大概率是用了字符串语法而非数组语法,Laravel会忽略参数,等价于无参放行。
第四步:避免混用写法,在Route::group中统一使用数组语法,例如->middleware(['auth', 'role:admin']),不要穿插middleware('auth')和middleware(['role:admin'])。











