Laravel 8 中路由文件中使用中间件方法失败的原因是什么?

What causes this failure to use a middleware method in the routes file, in Laravel 8?

我正在开发具有用户、角色和权限的 Laravel 8 应用程序。我使用 Microsoft Azure 进行用户登录。

我开始在他们的网站上关注 this tutorial

我从 permissions MySQL table 中获得了针对每个用户角色的 逗号分隔用户权限 列表。

我希望当前用户可以访问某些路由,具体取决于他们拥有的权限

我将 userPermissions 变量存储在这样的会话中:

public function storeTokens($accessToken, $user, $user_role, $user_permissions) {
    session([
      'accessToken' => $accessToken->getToken(),
      'refreshToken' => $accessToken->getRefreshToken(),
      'tokenExpires' => $accessToken->getExpires(),
      'userName' => $user->getDisplayName(),
      'firstName' => $user->getGivenName(),
      'lastName' => $user->getSurname(),
      'userRole' => $user_role,
      'userPermissions' => $user_permissions,
      'userEmail' => null !== $user->getMail() ? $user->getMail() : $user->getUserPrincipalName(),
      'userTimeZone' => $user->getMailboxSettings()->getTimeZone()
    ]);
}

我创建了一个新的中间件,叫做 CheckUserPermissions:

class CheckUserPermissions
{
    /**
     * Handle an incoming request.
     *
     * @param  \Illuminate\Http\Request  $request
     * @param  \Closure(\Illuminate\Http\Request): (\Illuminate\Http\Response|\Illuminate\Http\RedirectResponse)  $next
     * @return \Illuminate\Http\Response|\Illuminate\Http\RedirectResponse
     */

    private $permission;

    // Permissions checker
    public function hasPermissionTo($permission) {
        return in_array($permission, session('userPermissions'));
    }

    public function handle(Request $request, Closure $next)
    {
        // Check user permissions
        if (!$this->hasPermissionTo($this->permission)) {
            return redirect('/')->with('error', 'You do not have permission to access to this section of the application');
        }

        return $next($request);
    }
}

我在app\Http\Kernel.php注册了上面的中间件:

protected $routeMiddleware = [
    //More middleware
    'checkSignedIn' => \App\Http\Middleware\CheckSignedIn::class,
    'checkUserPermissions' => \App\Http\Middleware\CheckUserPermissions::class,
];

问题

问题是我无法在控制器外使用policy/gate(即使当前用户有查看用户的权限)。

routes\web.php 中执行 Route::get('/users', [UsersContoller::class, 'index'])->middleware('checkUserPermissions')->hasPermissionTo('view-users') 不起作用:

// Dashboard routes
Route::group(['prefix' => 'dashboard', 'middleware' => ['checkSignedIn']], function() {
    Route::get('/', [DashboardContoller::class, 'index'])->name('dashboard');
    Route::get('/users', [UsersContoller::class, 'index'])->middleware('checkUserPermissions')->hasPermissionTo('view-users');
});

它导致在浏览器中显示 Method Illuminate\Routing\Route::hasPermissionTo does not exist 错误

我做错了什么?

您无法访问路由定义中的中间件方法。中间件只运行 handle 方法,因此您在编写代码时应牢记这一点。解决方法如下:

class CheckUserPermissions
{
    /**
     * Handle an incoming request.
     *
     * @param  \Illuminate\Http\Request  $request
     * @param  \Closure(\Illuminate\Http\Request): (\Illuminate\Http\Response|\Illuminate\Http\RedirectResponse)  $next
     * @return \Illuminate\Http\Response|\Illuminate\Http\RedirectResponse
     */

    private $permission;

    // Permissions checker
    public function hasPermissionTo($permission) {
        return in_array($permission, session('userPermissions'));
    }

    public function handle(Request $request, Closure $next, ...$permissions)
    {
        // Check user permissions
        foreach ($permissions as $permission) {
            if (!$this->hasPermissionTo($permission)) { 
               return redirect('/')->with('error', 'You do not have permission to access to this section of the application');
            }
        }

        return $next($request);
    }
}

并将中间件用作:

Route::group(['prefix' => 'dashboard', 'middleware' => ['checkSignedIn']], function() {
    Route::get('/', [DashboardContoller::class, 'index'])->name('dashboard');
    Route::get('/users', [UsersContoller::class, 'index'])->middleware('checkUserPermissions:view-users');
});

checkUserPermissions:view-users: 之后的任何内容都作为 handle 方法的附加参数发送。您也可以发送多个:

Route::get('/users', [UsersContoller::class, 'index'])->middleware('checkUserPermissions:view-users,see-users,glance-at-users');

逗号分隔列表中的每个项目都是中间件 $permissions 数组中的附加数组条目