Может войдёшь?
Черновики Написать статью Профиль

Авторизация

перевод документация 5.х

  1. 1. Определение прав
    1. 1.1. Права на основе класса
    2. 1.2. Перехват проверок авторизации
  2. 2. Проверка прав
    1. 2.1. С помощью фасада Gate
    2. 2.2. С помощью модели User
    3. 2.3. В шаблонах Blade
    4. 2.4. В запросах форм
  3. 3. Политики
    1. 3.1. Создание политик
    2. 3.2. Написание политик
    3. 3.3. Проверка политик
  4. 4. Авторизация контроллера
Этот перевод актуален для англоязычной документации на (ветка 5.1). Опечатка? Выдели и нажми Ctrl+Enter.

В Laravel сразу после установки есть сервисы аутентификации, а также он обеспечивает простой способ организовать логику авторизации и контролировать доступ к ресурсам. Существует множество методов и вспомогательных функций, предназначенных для организации вашей логики авторизации, и в данном документе мы рассмотрим каждый из них.

Авторизация была добавлена в Laravel 5.1.11, поэтому обратитесь к руководству по обновлению перед добавлением этих возможностей в своё приложение.

Определение прав

Простейший способ определить наличие у пользователя прав на выполнение конкретного действия — задать «право» при помощи класса Illuminate\Auth\Access\Gate. Поставляемый с Laravel AuthServiceProvider служит удобным местом для определения всех прав для вашего приложения. Например, давайте определим право update-post, которое получает текущего User и модель Post. Внутри нашего права мы будем проверять совпадает ли id пользователя с user_id статьи:

PHP
<?php

namespace App\Providers;

use 
Illuminate\Contracts\Auth\Access\Gate as GateContract;
use 
Illuminate\Foundation\Support\Providers\AuthServiceProvider as ServiceProvider;

class 
AuthServiceProvider extends ServiceProvider
{
  
/**
   * Регистрация любых сервисов аутентификации/авторизации для приложения.
   *
   * @param  \Illuminate\Contracts\Auth\Access\Gate  $gate
   * @return void
   */
  
public function boot(GateContract $gate)
  {
    
$this->registerPolicies($gate);

    
$gate->define('update-post', function ($user$post) {
      return 
$user->id === $post->user_id;
    });
  }
}

Заметьте, мы не проверили данного $user на NULL. Gate автоматически вернёт значение false для всех прав, когда нет аутентифицированного пользователя, или конкретный пользователь не был указан с помощью метода PHPforUser().

Права на основе класса

В добавление к регистрации замыканий Closures в качестве обратных вызовов авторизации, вы можете регистрировать методы класса, передавая строку с именем класса и метода. Когда понадобится, класс будет извлечён при помощи сервис-контейнера:

PHP
$gate->define('update-post''Class@method');

Перехват проверок авторизации

Иногда необходимо предоставить полные права конкретному пользователю. Для таких случаев используйте метод PHPbefore(), чтобы задать обратный вызов, который будет выполняться до всех остальных проверок авторизации:

PHP
$gate->before(function ($user$ability) {
  if (
$user->isSuperAdmin()) {
    return 
true;
  }
});

Если обратный вызов PHPbefore() возвращает не пустой результат, то этот результат будет считаться результатом проверки.

Вы можете использовать метод PHPafter() для задания обратного вызова, который будет выполняться после каждой проверки авторизации. Но из этого метода нельзя изменить результат проверки авторизации:

PHP
$gate->after(function ($user$ability$result$arguments) {
  
//
});

Проверка прав

С помощью фасада Gate

Когда право задано, мы можем «проверить» его разными способами. Во-первых, мы можем использовать методы фасада GatePHPcheck(), PHPallows() и PHPdenies(). Все они получают имя права и аргументы, которые необходимо передать в обратный вызов права. Вам не надо передавать текущего пользователя в эти методы, поскольку Gate автоматически подставит его перед аргументами, передаваемыми в обратный вызов. Поэтому при проверке права update-post, которое мы определили ранее, нам надо передать только экземпляр Post в метод PHPdenies():

PHP
<?php

namespace App\Http\Controllers;

use 
Gate;
use 
App\User;
use 
App\Post;
use 
App\Http\Controllers\Controller;

class 
PostController extends Controller
{
  
/**
   * Обновление данной статьи.
   *
   * @param  int  $id
   * @return Response
   */
  
public function update($id)
  {
    
$post Post::findOrFail($id);

    if (
Gate::denies('update-post'$post)) {
      
abort(403);
    }

    
// Обновление статьи...
  
}
}

Метод PHPallows() обратен методу PHPdenies() и возвращает true, если действие авторизовано. Метод PHPcheck() — псевдоним метода PHPallows().

Проверка прав конкретного пользователя

Если вы хотите использовать фасад Gate для проверки наличия определённого права у пользователя, отличного от текущего аутентифицированного пользователя, то можете использовать метод PHPforUser():

PHP
if (Gate::forUser($user)->allows('update-post'$post)) {
  
//
}

Передача нескольких аргументов

Конечно, обратные вызовы прав могут принимать несколько аргументов:

PHP
Gate::define('delete-comment', function ($user$post$comment) {
  
//
});

Если вашему праву необходимо несколько аргументов, просто передайте массив аргументов в методы Gate:

PHP
if (Gate::allows('delete-comment', [$post$comment])) {
    
//
}

С помощью модели User

Альтернативный способ проверки прав — с помощью экземпляра модели User. По умолчанию в Laravel модель App\User использует типаж Authorizable, который предоставляет два метода: PHPcan() и PHPcannot(). Эти методы могут быть использованы так же, как методы PHPallows() и PHPdenies() фасада Gate. Тогда, используя наш предыдущий пример, мы можем изменить код вот так:

PHP
<?php

namespace App\Http\Controllers;

use 
App\Post;
use 
Illuminate\Http\Request;
use 
App\Http\Controllers\Controller;

class 
PostController extends Controller
{
  
/**
   * Обновление данной статьи.
   *
   * @param  \Illuminate\Http\Request  $request
   * @param  int  $id
   * @return Response
   */
  
public function update(Request $request$id)
  {
    
$post Post::findOrFail($id);

    if (
$request->user()->cannot('update-post'$post)) {
      
abort(403);
    }

    
// Обновление статьи...
  
}
}

Метод PHPcan() обратен методу PHPcannot():

PHP
if ($request->user()->can('update-post'$post)) {
  
// Обновление статьи...
}

В шаблонах Blade

Для удобства Laravel предоставляет Blade-директиву @can для быстрой проверки наличия данного права у текущего аутентифицированного пользователя. Например:

PHP
<a href="/post/{{ $post->id }}">View Post</a>

@
can('update-post'$post)
    <
a href="/post/{{ $post->id }}/edit">Edit Post</a>
@
endcan

Также вы можете комбинировать директиву @can с директивой @else:

PHP
@can('update-post'$post)
    <!-- 
The Current User Can Update The Post -->
@else
    <!-- 
The Current User Can't Update The Post -->
@endcan

В запросах форм

Также вы можете использовать определёные в Gate права в методе PHPauthorize() запроса формы. Например:

PHP
/**
 * Определение авторизации пользователя для выполнения этого запроса.
 *
 * @return bool
 */
public function authorize()
{
  
$postId $this->route('post');

  return 
Gate::allows('update'Post::findOrFail($postId));
}

Политики

Создание политик

В больших приложениях определение всей логики авторизации в AuthServiceProvider может стать громоздким, поэтому Laravel позволяет вам разделять вашу логику авторизации на классы «Политики». Политики — простые PHP-классы, которые группируют логику авторизации на основе авторизуемых ресурсов.

Сначала давайте сгенерируем политику для управления авторизацией для нашей модели Post. Вы можете сгенерировать политику используя artisan-команду shmake:policy. Сгенерированная политика будет помещена в папку app/Policies:

shphp artisan make:policy PostPolicy

Регистрация политик

Когда мы создали политику, нам надо зарегистрировать её классом Gate. AuthServiceProvider содержит свойство policies, которое сопоставляет различные сущности с управляющими ими политиками. Поэтому мы укажем, что политика модели Post — это класс PostPolicy:

PHP
<?php

namespace App\Providers;

use 
App\Post;
use 
App\Policies\PostPolicy;
use 
Illuminate\Foundation\Support\Providers\AuthServiceProvider as ServiceProvider;

class 
AuthServiceProvider extends ServiceProvider
{
  
/**
   * Сопоставление политик для приложения.
   *
   * @var array
   */
  
protected $policies = [
    
Post::class => PostPolicy::class,
  ];

  
/**
   * Регистрация любых сервисов аутентификации/авторизации для приложения.
   *
   * @param  \Illuminate\Contracts\Auth\Access\Gate  $gate
   * @return void
   */
  
public function boot(GateContract $gate)
  {
    
$this->registerPolicies($gate);
  }
}

Написание политик

Когда политика сгенерирована и зарегистрирована, мы можем добавлять методы для каждого права, за которое она отвечает. Например, определим метод PHPupdate() в нашем PostPolicy, который будет проверять может ли данный User «обновлять» Post:

PHP
<?php

namespace App\Policies;

use 
App\User;
use 
App\Post;

class 
PostPolicy
{
  
/**
   * Проверка может ли данный пост быть обновлён пользователем.
   *
   * @param  \App\User  $user
   * @param  \App\Post  $post
   * @return bool
   */
  
public function update(User $userPost $post)
  {
    return 
$user->id === $post->user_id;
  }
}

При необходимости вы можете продолжить определять дополнительные методы для политики для различных прав, за которые она отвечает. Например, вы можете определить методы PHPshow(), PHPdestroy() и PHPaddComment() для авторизации различных действий с Post.

Все политики подключаются через сервис-контейнер Laravel, а значит, вы можете указать типы любых необходимых зависимостей в конструкторе политики, и они будут внедрены автоматически.

Перехват всех проверок

Если вам необходимо предоставить конкретному пользователю все права политики, определите в этой политике метод PHPbefore(). Этот метод будет выполняться до всех остальных проверок авторизации этой политики:

PHP
public function before($user$ability)
{
  if (
$user->isSuperAdmin()) {
    return 
true;
  }
}

Если метод PHPbefore() возвращает не пустой результат, то этот результат будет считаться результатом проверки.

Проверка политик

Методы политик вызываются точно так же, как обратные вызовы авторизации на основе замыканий Closure. Вы можете использовать фасад Gate, модель User, Blade-директиву @can, или вспомогательную функцию PHPpolicy().

С помощью фасада Gate

Gate автоматически определяет какую политику использовать, исходя из классов аргументов, передаваемых в его методы. Если мы передаём экземпляр Post в метод denies, то Gate будет использовать соответствующий PostPolicy для авторизации действий:

PHP
<?php

namespace App\Http\Controllers;

use 
Gate;
use 
App\User;
use 
App\Post;
use 
App\Http\Controllers\Controller;

class 
PostController extends Controller
{
  
/**
   * Обновление данной статьи.
   *
   * @param  int  $id
   * @return Response
   */
  
public function update($id)
  {
    
$post Post::findOrFail($id);

    if (
Gate::denies('update'$post)) {
      
abort(403);
    }

    
// Обновление статьи...
  
}
}

С помощью модели User

Методы PHPcan() и PHPcannot() модели User будут так же автоматически использовать политики, когда они доступны для данных аргументов. Эти методы предоставляют удобный способ для авторизации действий для любого экземпляра User, получаемого вашим приложением:

PHP
if ($user->can('update'$post)) {
  
//
}

if (
$user->cannot('update'$post)) {
  
//
}

В шаблонах Blade

Точно так же Blade-директива @can будет использовать политики, когда они доступны для данных аргументов:

PHP
@can('update'$post)
  <!-- 
Текущий Пользователь Может Обновлять Статью -->
@
endcan

С помощью вспомогательной функции Policy

Глобальная вспомогательная функция PHPpolicy() может использоваться для получения класса Policy для данного экземпляра класса. Например, мы можем передать экземпляр Post в функцию PHPpolicy() для получения экземпляра соответствующего класса PostPolicy:

PHP
if (policy($post)->update($user$post)) {
  
//
}

Авторизация контроллера

Базовый класс Laravel App\Http\Controllers\Controller по умолчанию использует типаж AuthorizesRequests. Этот типаж предоставляет метод PHPauthorize(), который может быть использован для быстрой авторизации данного действия или выброса HttpException, если действие не авторизовано.

Метод PHPauthorize() разделяет ту же подпись, что и различные другие методы авторизации, такие как PHPGate::allows и PHP$user->can(). Давайте используем метод PHPauthorize() для быстрой авторизации запроса на обновление Post:

PHP
<?php

namespace App\Http\Controllers;

use 
App\Post;
use 
App\Http\Controllers\Controller;

class 
PostController extends Controller
{
  
/**
   * Обновление данной статьи.
   *
   * @param  int  $id
   * @return Response
   */
  
public function update($id)
  {
    
$post Post::findOrFail($id);

    
$this->authorize('update'$post);

    
// Обновление статьи...
  
}
}

Если действие авторизовано, контроллер продолжит нормально выполняться; но если метод PHPauthorize() определит, что действие не авторизовано, будет автоматически выброшено HttpException, которое сгенерирует HTTP-ответ с кодом состояния 403 Not Authorized. Как видите, метод PHPauthorize() — удобный и быстрый способ авторизации действия или выброса исключения одной строчкой кода.

Типаж AuthorizesRequests также предоставляет метод PHPauthorizeForUser() для авторизации действия для пользователя, который не является текущим аутентифицированным пользователем:

PHP
$this->authorizeForUser($user'update'$post);

Автоматическое определение методов политики

Часто методы политики будут соответствовать методам контроллера. Например, в приведённом выше методе PHPupdate() у метода контроллера и метода политики одинаковое название PHPupdate().

Поэтому Laravel позволяет просто передать аргументы экземпляра в метод PHPauthorize(), и авторизуемое действие будет автоматически определено на основе имени вызываемой функции. В этом примере, поскольку PHPauthorize() вызывается из метода контроллера PHPupdate(), то и в политике будет вызван метод PHPupdate():

PHP
/**
 * Обновление данной статьи.
 *
 * @param  int  $id
 * @return Response
 */
public function update($id)
{
    
$post Post::findOrFail($id);

    
$this->authorize($post);

    
// Обновление статьи...
}

Комментарии (2)

FreeStyler

Что-то так и не понял как установить права... Самому создавать таблицы и потом по ним определять при аутентификации как в последнем сообщении в forum/viewtopic.php?id=826 или таки дальше использовать entrust ?

jdfghfd

Как определять права для гостей?

Написать комментарий

Разметка: ? ?

Авторизуйся, чтобы прокомментировать.