Laravel 6 выполнять маршрутизацию на основе ролей - PullRequest
0 голосов
/ 10 июля 2020

У меня есть группа маршрутов с разными маршрутами. Я хочу иметь доступ к разным уровням ролей без изменения URL-адреса приложения.

Например, я хочу использовать / admin в качестве маршрута, а затем я хочу разрешить или запретить пользователям в зависимости от их ролей. По сути, я хочу, чтобы каждый пользователь мог видеть одну и ту же страницу, но с разными параметрами меню (я знаю, как это сделать), но также защищал ссылки от прямого доступа.

Есть ли хороший способ добиться этого? без необходимости использования разных промежуточных программ на каждом маршруте? Поскольку, похоже, нет способа получить переменную $ request внутри файла web. php, а только внутри контроллера. Я использую пакет sentinel для аутентификации.

Пример кода моего веб-сайта. 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();  
}

Ответы [ 2 ]

1 голос
/ 10 июля 2020

Я уже отвечал на что-то подобное раньше, должно работать так же.

Вы можете создать промежуточное ПО, которое можно применить к вашей группе. В этом промежуточном программном обеспечении он запрашивает сам маршрут для проверки указанных c ролей.

Как назначить два промежуточного программного обеспечения одной и той же группе маршрутов. 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(...);
0 голосов
/ 10 июля 2020

Вы можете использовать Laravel Шлюз и политики

Вы можете определить шлюз внутри App > Providers > AuthServiceProvider

, а также можете создавать политики для CRUD . просто смотрите информацию в php artisan help make:policy. Это создаст папку в ваших app, называемых политиками, вы можете определить, кто может получить к ней доступ.

В вашем контроллере вы можете сделать следующее: (это промежуточное программное обеспечение шлюза)

I сначала определите ворота:

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

EDIT: Controller

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