Laravel Sanctum结合Spatie权限:配置用户与管理员权限
解决方案
1. 先修复令牌生成的错误
你当前生成令牌时传入了二维数组,这会导致Sanctum的权限验证异常。$user->getRoleNames()->toArray()本身已经是一维数组(比如['user']),不需要再嵌套一层数组。修改代码如下:
$user->createToken($user->name, $user->getRoleNames()->toArray())->plainTextToken;
2. 配置Spatie角色权限中间件
确保Spatie的Laravel Permission包已完成安装迁移,然后在app/Http/Kernel.php的$routeMiddleware中注册角色中间件:
'role' => \Spatie\Permission\Middlewares\RoleMiddleware::class,
3. 用Policy实现细粒度权限控制
这种方式能精准控制每个操作的权限,适配你需要的「user仅能操作自身,admin可操作所有」的场景。
生成User Policy
执行命令创建对应模型的Policy:
php artisan make:policy UserPolicy --model=User
编写Policy逻辑
打开app/Policies/UserPolicy.php,添加以下权限判断:
<?php namespace App\Policies; use App\Models\User; class UserPolicy { // 查看用户信息权限 public function view(User $user, User $targetUser) { return $user->hasRole('admin') || $user->id === $targetUser->id; } // 更新用户信息权限 public function update(User $user, User $targetUser) { return $user->hasRole('admin') || $user->id === $targetUser->id; } // 删除用户权限(按需添加) public function delete(User $user, User $targetUser) { return $user->hasRole('admin'); } }
注册Policy
在app/Providers/AuthServiceProvider.php的$policies数组中绑定Policy和模型:
protected $policies = [ \App\Models\User::class => \App\Policies\UserPolicy::class, ];
在控制器中应用授权
在UserController的对应方法里调用authorize方法,触发权限验证:
// 查看单个用户 public function show(User $user) { $this->authorize('view', $user); return response()->json($user); } // 更新用户信息 public function update(Request $request, User $user) { $this->authorize('update', $user); $user->update($request->validated()); return response()->json($user); }
4. 可选:路由层面的权限分流
如果想直接在路由层限制角色访问范围,可以拆分路由:
Route::middleware('auth:sanctum')->group(function () { // admin专属:完整操作所有用户 Route::middleware('role:admin')->group(function () { Route::apiResource('users', UserController::class); }); // user专属:仅能操作自身信息 Route::middleware('role:user')->group(function () { Route::get('users/me', [UserController::class, 'showMe']); Route::put('users/me', [UserController::class, 'updateMe']); }); });
然后在UserController中添加两个方法:
public function showMe() { return response()->json(auth()->user()); } public function updateMe(Request $request) { $user = auth()->user(); $user->update($request->validated()); return response()->json($user); }
这样user角色无法访问/users/{id}这类接口,只能通过/users/me操作自身数据,避免越权访问。
内容的提问来源于stack exchange,提问作者Hopex Development
相关产品推荐
相关产品推荐

