Laravel 6 执行基于角色的路由

Laravel 6 perform role based routing

我有一个包含不同路线的路线组。我想在不更改应用程序 URL 的情况下拥有不同的角色级别访问权限。

例如,我想将 /admin 作为路由,然后我想根据用户的角色允许或禁止用户。基本上,我希望每个用户都能够看到相同的页面,但具有不同的菜单选项(我知道如何做到这一点),但也要确保链接不被直接访问。

有没有一种不需要在每条路由上分别使用不同中间件的好方法?由于似乎没有办法在 web.php 文件中检索 $request 变量,而只能在控制器中检索。我正在使用 sentinel 包进行身份验证。

我的一些示例代码 web.php:

Route::group(
['prefix' => 'admin', 'middleware' => 'customer', 'as' => 'admin.'],
function () {
    // Ad list
    Route::get('getMyAnnonsList', 'Admin\BackEndController@getMyAdList')->name('getMyAdList');       
    }
);

@lagbox 的回答很棒。这就是我最后所做的。很优雅。

web.php:

Route::group(['prefix' => 'admin', 'as' => 'admin.'], function () {
Route::middleware('admin:admin,user')->group(function(){
            Route::get('getMyAnnonsList', 'Admin\BackEndController@getMyAdList')->name('getMyAdList'); 
        });
});

中间件:

public function handle($request, Closure $next, ...$roles)
{      
    if (!Sentinel::check()) 
        return redirect('admin/signin')->with('info', 'You must be logged in!');
     
    foreach($roles as $role)        
        if($role == Sentinel::getUser()->roles[0]->slug)
            return $next($request);        
   
    return redirect()->back();  
}

您可以使用Laravel Gate And Policies

您可以在 App > Providers > AuthServiceProvider

内定义门

您还可以根据 CRUD 创建策略。只需查看 php artisan help make:policy 中的信息。这将在您的 app 中创建一个名为策略的文件夹,您可以定义谁可以访问它。

在你的控制器中你可以这样做:(这是一个门中间件)

我先定义门:

Gate::define('check', function ($user, $request) {
  return $user->roles->contains('name', $request) || $user->roles->contains('name', 'root');
});

然后我在控制器中初始化它

abort_if(Gate::denies('check', 'admin only'), 403);

如果用户无权访问该角色,这将引发 403 错误。它将检查用户是否具有 admin only 角色。如果没有它会抛出错误

在您看来,如果您想禁用 anchor links,您可以这样做:

@can('check', 'admin only')
  <a href="/admin/dashboard">dashboard</a>
@endcan

编辑: 控制器

public function index() {
  abort_if(Gate::denies('check', 'admin only'), 403);
  // Your Code...
}

我之前已经回答过类似的问题,应该还是一样。

您可以创建一个可以应用于您的组的中间件。在该中间件中,它要求路由本身检查特定角色。

How to assign two middleware to the same group of routes. Laravel

中间件示例:

class CheckMiddleware
{
    public function handle($request, Closure $next)
    {
        $roles = $request->route()->getAction('roles', []);

        foreach ((array) $roles as $role) {
            // if the user has this role, let them pass through
            if (...) {
                return $next($request);
            }
        }

        // user is not one of the matching 'roles'
        return redirect('/');
    }
}

示例路由定义:

Route::middleware('rolescheck')->group(function () {
    Route::get('something', ['uses' => 'SomeController@method', 'roles' => [...]])->name(...);
});

您可以在组级别、个人路由级别或两者应用此任意数据,因为所有路由都是单独注册的;组仅允许级联配置。

你也可以让这个中间件带参数,然后将它们与任意角色合并,那么它就是一个双重用途的中间件:

public function handle($request, $next, ...$roles)
{
    $roles = array_merge($roles, $request->route()->getAction('roles', []));
    ...
}

Route::middleware('rolescheck:admin,staff')->group(...);