You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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']);

三、注意事项

  1. 确保User模型正确引入Spatie Trait:你的User模型必须使用Spatie\Permission\Traits\HasRoles trait,否则Auth::user()不会有can()等权限相关方法:
use Spatie\Permission\Traits\HasRoles;

class User extends Authenticatable
{
    use HasRoles;
    // ... 其他代码
}
  1. 中间件顺序:auth:sanctum必须放在权限中间件之前,只有先完成认证,才能获取到当前用户进行权限校验。

内容的提问来源于stack exchange,提问作者SScotti

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.09 09:05:23