Как проверить, есть ли у пользователя разрешение на доступ к этой функции в Laravel

У меня есть функция, которая проверяет, есть ли у пользователя разрешение, и возвращает Логический.

Вопрос

Как я проверяю, есть ли у пользователя каждой функции разрешение или нет. Например, в пользовательский контроллер у меня есть 2 функции:

  1. index (): показать всех пользователей
  2. delete ($ id): удалить одного пользователя

показатель():

public function index () {
    if (Auth::user() -> hasPermissionTo('show all users')) {
        // continue for API
    } else {
        // response with error for API
    }
}

Я знаю, что есть лучший способ сделать это, потому что я не хочу повторять этот оператор if во всех своих функциях.

Что я пытался сделать:

Я попытался создать вспомогательную функцию, которая проверяет, есть ли у пользователя разрешение, и возвращает ошибку ответа, если у пользователя нет разрешения. И вызывайте его в каждой функции, но это не сработало.

Код вспомогательной функции:

if (!function_exists('userHasPermission')) {
    function userHasPermission ($permission) {
        $main_permission = 'do everything';
        if (!Auth::user() -> hasPermissionTo($main_permission) || !Auth::user() -> hasPermissionTo($permission)) {
            $res = trans('api_responses.authorization_failed');
            return Response::json([
                'message'   =>  $res['message'],
                'code'      =>  $res['code']
            ], $res['code']);
        }
    }
}

вызов функции индекса

public function index()
    {
        // PERMISSIONS CHECK
        userHasPermission('users show active');
        $getUsers = $this -> users -> getAllActive();
        return Response::json($getUsers);
    }

Но он никогда не возвращает ответ об ошибке, даже если у пользователя нет разрешения, и даже он ввел оператор if в моем помощнике!

Вы должны прочитать laravel.com/docs/5.7/authorization.

ceejayoz 04.10.2018 18:05

@ceejayoz Да, я прочитал это, но моя проблема в том, что я не хочу проверять if else во всех функциях своих контроллеров

Ahmed essam 05.10.2018 00:34
Стоит ли изучать PHP в 2026-2027 годах?
Стоит ли изучать PHP в 2026-2027 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Symfony Station Communiqué - 7 июля 2023 г
Symfony Station Communiqué - 7 июля 2023 г
Это коммюнике первоначально появилось на Symfony Station .
Оживление вашего приложения Laravel: Понимание режима обслуживания
Оживление вашего приложения Laravel: Понимание режима обслуживания
Здравствуйте, разработчики! В сегодняшней статье мы рассмотрим важный аспект управления приложениями, который часто упускается из виду в суете...
Установка и настройка Nginx и PHP на Ubuntu-сервере
Установка и настройка Nginx и PHP на Ubuntu-сервере
В этот раз я сделаю руководство по установке и настройке nginx и php на Ubuntu OS.
Коллекции в Laravel более простым способом
Коллекции в Laravel более простым способом
Привет, читатели, сегодня мы узнаем о коллекциях. В Laravel коллекции - это способ манипулировать массивами и играть с массивами данных. Благодаря...
Как установить PHP на Mac
Как установить PHP на Mac
PHP - это популярный язык программирования, который используется для разработки веб-приложений. Если вы используете Mac и хотите разрабатывать...
1
2
17 151
4
Перейти к ответу Данный вопрос помечен как решенный

Ответы 4

Ваша вспомогательная функция возвращает новый ответ, но он возвращает его контроллеру не как HTTP-ответ, поэтому вы можете получить возвращаемое значение следующим образом:

public function index()
    {
        // PERMISSIONS CHECK
        $response = userHasPermission('users show active');


        $getUsers = $this -> users -> getAllActive();
        return Response::json($getUsers);
    }

Итак, вам нужно проверить ответ, имеет ли он значение но при таком подходе вы столкнетесь с той же проблемой, что и ваш первый.

Чтобы решить эту проблему: выбросите исключение из вспомогательной функции вместо того, чтобы возвращать какой-либо ответ.

Лучшее решение должен использовать FormRequest, проверьте этот ссылка, чтобы сделать это, не забудьте проверить раздел «Авторизация запросов формы», в котором указана функция авторизации.

Обновлено:

вам нужно сделать следующее:

создайте новый класс, назовем его «IndexRequest», который наследуется от класса «FormRequest», а затем реализуем метод авторизации.

так что-то вроде этого:

class IndexRequest extends FormRequest
{
      /**
      * Determine if the user is authorized to make this request.
      *
      * @return bool
      */
      public function authorize()
      {
          return Auth::user() -> hasPermissionTo('show all users');
      }

          /**
      * Get the validation rules that apply to the request.
      *
      * @return array
      */
     public function rules()
     {
         return [
         ];
     }
 }

то в вашем методе:

public function index(IndexRequest $request)
{
   $getUsers = $this -> users -> getAllActive();
   return Response::json($getUsers);
}

Вам не нужно проверять это вручную, Laravel сделает это за вас, используя функцию «авторизовать» класса IndexRequest.

Проблема в том, что я не хочу делать этот оператор if в каждой функции в каждом контроллере.

Ahmed essam 05.10.2018 00:32

Вы должны проверить ссылку, которую я дал в своем ответе! Я думаю, вам нужно добавить "FormRequest", пожалуйста, прочтите документацию!

Ahmed Nour Jamal El-Din 05.10.2018 06:26
Ответ принят как подходящий

В Laravel для этого можно использовать гейт.

В вашем файле App \ Providers \ AuthServiceProvider сделайте что-то вроде этого:

public function boot()
{
    $this->registerPolicies();

    Gate::define('do-everything', function ($user) {
        return $user->hasPermission('do-everything');
    });

    Gate::define('do-one-thing', function ($user) {
        return $user->hasPermission('do-one-thing');
    });
}

А затем в вашем контроллере:

if (Auth::user()->can('do-everything')) {
    // the user can do everything
}

if (Auth::user()->can('do-one-thing')) {
    // the user can just do one thing
}

или

if (!Auth::user()->can('do-everything')) {
    abort(403);
}
// user has permission to the everything from here on

или в ваших маршрутах / web.php вы можете сделать это:

Route::get('/things', 'ThingController@action')->middleware(['can:do-one-thing']);

или вы можете сгруппировать маршруты следующим образом:

Route::middleware(['can:do-everything'])->group(function () {
    Route::get('/things', 'ThingController@index');
    Route::get('/other-things', 'OtherThingController@index');
    ...
}

Вы также можете посмотреть https://laravel.com/docs/5.7/authorization для получения дополнительных идей.

Моя проблема в том, что я не хочу делать этот оператор if else в каждом контроллере, поэтому я ищу лучший метод.

Ahmed essam 04.10.2018 23:36

Я уже сделал это, и я могу использовать can('do-everything'), но я буду делать то же самое if для каждой функции контроллера.

Ahmed essam 04.10.2018 23:39

@Ahmedessam Вы также можете поместить это в свои маршруты, чтобы он не попал в ваши контроллеры. Смотрите обновление в моем ответе.

Peter 05.10.2018 02:40

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

Ahmed essam 05.10.2018 22:59

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

Ahmed essam 05.10.2018 22:59

Этот способ проверить несколько разрешений, чтобы решить, шо

  @php
                        $patients_menu_item=0;
                        $users_menu_item=0;
                        $roles_menu_item=0;
                            if (Auth::user() -> hasPermissionTo('Patient Add')||Auth::user() -> hasPermissionTo('Patients List')) {
                              $patients_menu_item=1;
                            }
                            if (Auth::user() -> hasPermissionTo('User Add')||Auth::user() -> hasPermissionTo('Users List')) {
                              $users_menu_item=1;
                            }
                            if (Auth::user() -> hasPermissionTo('Role Add')||Auth::user() -> hasPermissionTo('Roles List')) {
                              $roles_menu_item=1;
                            }
                    @endphp
                    @if ($patients_menu_item == 1)
                        <li class = "has-sub">
                            <a>
                                <i class = "ft-users"></i><span class = "menu-title">Patients</span>
                            </a>
                            <ul class = "menu-content">
                                @can('Patient Add')
                                    <li>
                                        <a href = "{{url('patients/register')}}"
                                           class = "menu-item">Register Patient</a>
                                    </li>
                                @endcan
                                @can('Patients List')
                                    <li>
                                        <a href = "{{url('patients/index')}}"
                                           class = "menu-item">{{ trans('website.Show Patients') }}</a>
                                    </li>
                                @endcan
                            </ul>
                        </li>
                    @endif

Еще один простой способ проверить разрешение внутри контроллера

use Illuminate\Http\Request; //don't forget to include on top
public function index(Request $request)
{
   if ($request->user()->canDo('permission you need to check'))
      userHasPermission('users show active');
      $getUsers = $this -> users -> getAllActive();
      return Response::json($getUsers);
   }
   return Response::json(['Unaurthrorized']);
}

Другие вопросы по теме