Laravel多角色中间件

34

我一直在使用Laravel的中间件遇到了一些问题。让我告诉你我尝试实现的基本思路:

网站上的注册用户将有四种角色之一:

  1. 学生 (默认):可以访问 'index'和'show'视图
  2. 审核员:可以访问前面的内容,还可以访问 'overview', 'update'
  3. 编辑:可以访问前面的内容,还可以访问 'create', 'edit' 和 'store'
  4. 管理员:可以访问所有内容

提示:'overview'是一种索引视图,但仅适用于审核员及以上角色。

你们认为最好的方法是什么?这是我迄今为止所做的,但似乎不起作用:


Kernel.php

protected $middlewareGroups = [
...
    'approver+' => [
        \App\Http\Middleware\Approver::class,
        \App\Http\Middleware\Editor::class,
        \App\Http\Middleware\Admin::class,
    ],
];

protected $routeMiddleware = [
...
    'student' => \App\Http\Middleware\Student::class,
    'approver' => \App\Http\Middleware\Approver::class,
    'editor' => \App\Http\Middleware\Editor::class,
    'admin' => \App\Http\Middleware\Admin::class,
];

Http\Middleware\Admin.php

public function handle($request, Closure $next)
{
   if (Auth::check())
   {

        if(Auth::user()->isAdmin())
        {
            return $next($request);
        }
   }

    return redirect('login');
}

'User'是Eloquent模型:

public function isAdmin()
{
    if($this->role_id === 4)
    { 
        return true; 
    } 
    else 
    { 
        return false; 
    }
}

在审批者和编辑者中间件文件中,以及用户模型中的isApprover和isEditor函数中,我已经做了完全相同的操作,只是将if语句中的checked值分别编辑为2和3。

最后,这是我在routes\web文件中所做的:

Route::get('scholen', 'SchoolsController@index');
Route::get('admin/scholen/overzicht', 'SchoolsController@overview')->middleware('approver+');
Route::get('admin/scholen/maken', 'SchoolsController@create')->middleware('approver+');
Route::post('scholen', 'SchoolsController@store')->middleware('approver+');
Route::get('scholen/{id}', 'SchoolsController@show');
Route::get('admin/scholen/{id}/bewerken', 'SchoolsController@edit')->middleware('admin');
Route::patch('admin/scholen/{id}', 'SchoolsController@update')->middleware('admin');
Route::delete('admin/scholen/{id}', 'SchoolsController@destroy')->middleware('admin');

虽然还不是完全精准,但我现在卡住了,因为当我以具有批准者权限的用户身份登录并尝试访问学校概览时,它会将我重定向回主页。

总的来说,感觉我工作过于混乱,一切都不对头,能否有人给我提供如何更高效地完成工作的建议呢?

非常感谢您提前的帮助!

3个回答

90

你不应该为每个角色单独创建中间件,这会很快变得非常混乱。最好有一个单一的角色检查中间件,可以对传递给它的任何角色进行检查。

Http\Kernel.php

protected $routeMiddleware = [
    ...
    'role' => \App\Http\Middleware\Role::class,
];

Http\Middleware\Role.php

public function handle($request, Closure $next, ... $roles)
{
    if (!Auth::check()) // I included this check because you have it, but it really should be part of your 'auth' middleware, most likely added as part of a route group.
        return redirect('login');

    $user = Auth::user();

    if($user->isAdmin())
        return $next($request);

    foreach($roles as $role) {
        // Check if user has the role This check will depend on how your roles are set up
        if($user->hasRole($role))
            return $next($request);
    }

    return redirect('login');
}

最后,在您的网络路由中添加如下内容:

Route::get('admin/scholen/overzicht', 'SchoolsController@overview')->middleware('role:editor,approver');
Route::get('admin/scholen/{id}/bewerken', 'SchoolsController@edit')->middleware('role:admin');

1
我发现我把它搞得太复杂了 :) 这似乎很好用,非常感谢! - Jesse
9
三个点“...”拯救了我的生命 :) - FosAvance
1
@FosAvance 这个有趣的三个点“...”被称为常量表达式,它可以在 PHP 5.6.x 中使用 ;) 很有趣吧! :p - Md. Khalakuzzaman Khan
我正在使用 Laravel 7.x,但对我来说它是以字符串的形式出现的。请帮助我。 - Soubhagya Kumar Barik
做出如此干净的中间件,做得非常好,谢谢! - Rose Riyadh
显示剩余2条评论

4
这是对fafich回答的补充。
使用in_array而不是FOREACH,例如:
```php if (in_array($needle, $haystack)) { // do something } ```
if (! in_array($user->hasRole($role), $roles) {
 // returns if you dont have permission
}
return $next($request);

2
完善您的Handle函数以处理每个登录会话请求。
public function handle($request, Closure $next)
{
    if (! Auth::check()) {
        return redirect()->route('login');
    }

    if (Auth::user()->role == 1) {
        return redirect()->route('superadmin');
    }

    if (Auth::user()->role == 5) {
        return redirect()->route('academy');
    }

    if (Auth::user()->role == 6) {
        return redirect()->route('scout');
    }

    if (Auth::user()->role == 4) {
        return redirect()->route('team');
    }

    if (Auth::user()->role == 3) {
        return $next($request); 
    }

    if (Auth::user()->role == 2) {
        return redirect()->route('admin');
    }
}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接