Multiple middleware has permittion on same routes

2019-06-09 01:49发布

问题:

I have multi middleware (studen, parent, admin) and create some route group with that middleware. But some route can access if user is in any of that groups and belong in any of that middleware but not if is in other middleware fot example teacher. I use something like that in docs: http://laravel.com/docs/5.1/routing#route-groups But it's work when I put one route, when add another route group with another middleware it doesn't work. Is that possible and how to make it?

When I execute php artisan route it gives me an error

[Symfony\Component\Debug\Exception\FatalErrorException]
  Call to a member function inRole() on null

回答1:

Laravel's route middleware is executed one by one as declared in routes.php file. Therefore, if one of them denies access by throwing an exception or returning some respoise, the next middlewares won't be executed.

In order to make that work, you'll need a single middleware that would check if current user has any of required roles. Luckily, as of Laravel 5.1 you are able to pass parameters to middleware from your routes.php file (see http://laravel.com/docs/5.1/middleware#middleware-parameters), so you'll only need one middleware class to handle all cases.

Example middleware class could look like that:

class HasAnyRole
{
  public function handle($request, Closure $next, $roles)
  {
    // Return Not Authorized error, if user has not logged in
    if (!$request->user) {
      App::abort(401);
    }

    $roles = explode(',', $roles);
    foreach ($roles as $role) {
      // if user has given role, continue processing the request
      if ($request->user->hasRole($role)) {
        return $next($request);
      }
    }
    // user didn't have any of required roles, return Forbidden error
    App::abort(403);
  }  
}

Register the middleware in your Kernel.php:

protected $routeMiddleware = [
  'has_any_role' => 'App\Http\Middleware\HasAnyRole',
];

Now, in your routes.php you can apply the middleware to a group like that:

//this route is available only to users with role admin or author
Route::put('post/{id}', ['middleware' => 'has_any_role:admin,author', function ($id) {
    //
}]);

This should do the trick, just make sure that your User class has a hasRole method.