Вступление
В дополнение к предоставлению услуг аутентификации из коробки, Laravel также предоставляет простой способ авторизации действий пользователя с данным ресурсом. Подобно аутентификации, подход Laravel к авторизации прост, и есть два основных способа авторизации действий: ворота и политики.
Подумайте о воротах и политиках, таких как маршруты и контроллеры. Gates обеспечивает простой подход к авторизации на основе замыканий, в то время как политики, такие как контроллеры, группируют свою логику вокруг конкретной модели или ресурса. Сначала мы исследуем ворота, а затем рассмотрим правила.
Вам не нужно выбирать между исключительно использованием gates или исключительно использованием политик при создании приложения. Большинство приложений, скорее всего, будут содержать смесь ворот и политик, и это прекрасно! Ворота наиболее применимы к действиям, не связанным с какой-либо моделью или ресурсом, таким как просмотр панели администратора. Напротив, политики следует использовать, когда вы хотите авторизовать действие для конкретной модели или ресурса.
Gates
Написание Gates
Gates - это замыкания, которые определяют, авторизован ли пользователь для выполнения заданного действия, и обычно определяются в классе с использованием фасада. Гейтс всегда получает пользовательский экземпляр в качестве первого аргумента и может дополнительно получать дополнительные аргументы, такие как соответствующая модель Eloquent:App\Providers\AuthServiceProvider
Gate
/**
* Register any authentication / authorization services.
*
* @return void
*/
public function boot()
{
$this->registerPolicies();
Gate::define('update-post', function ($user, $post) {
return $user->id == $post->user_id;
});
}
Gates также могут быть определены с использованием Class@method
строки обратного вызова стиля, например, контроллеров:
/**
* Register any authentication / authorization services.
*
* @return void
*/
public function boot()
{
$this->registerPolicies();
Gate::define('update-post', 'App\Policies\PostPolicy@update');
}
Авторизация действий
Чтобы авторизовать действие, используя ворота, вы должны использовать методы allows
или denies
. Обратите внимание, что вы не обязаны передавать аутентифицированного пользователя этим методам. Laravel автоматически позаботится о пропуске пользователя в ворота. Закрытие:
if (Gate::allows('update-post', $post)) {
// The current user can update the post...
}
if (Gate::denies('update-post', $post)) {
// The current user can't update the post...
}
Если вы хотите определить, авторизован ли конкретный пользователь для выполнения действия, вы можете использовать forUser
метод на Gate
фасаде:
if (Gate::forUser($user)->allows('update-post', $post)) {
// The user can update the post...
}
if (Gate::forUser($user)->denies('update-post', $post)) {
// The user can't update the post...
}
Перехват чеков
Иногда вы можете пожелать предоставить все возможности конкретному пользователю. Вы можете использовать before
метод для определения обратного вызова, который выполняется перед всеми другими проверками авторизации:
Gate::before(function ($user, $ability) {
if ($user->isSuperAdmin()) {
return true;
}
});
Если before
обратный вызов возвращает ненулевой результат, этот результат будет считаться результатом проверки.
Вы можете использовать after
метод для определения обратного вызова, который будет выполнен после всех других проверок авторизации:
Gate::after(function ($user, $ability, $result, $arguments) {
if ($user->isSuperAdmin()) {
return true;
}
});
Аналогично before
проверке, если after
обратный вызов возвращает ненулевой результат, этот результат будет считаться результатом проверки.
Создание политик
Генерация политик
Политики - это классы, которые организуют логику авторизации вокруг конкретной модели или ресурса. Например, если ваше приложение представляет собой блог, у вас может быть Post
модель и соответствующая модель PostPolicy
для авторизации действий пользователя, таких как создание или обновление сообщений.
Вы можете создать политику, используя команду ремесленника . Сгенерированная политика будет помещена в каталог. Если этот каталог не существует в вашем приложении, Laravel создаст его для вас:make:policy
app/Policies
php artisan make:policy PostPolicy
Команда сгенерирует пустой класс политики. Если вы хотите сгенерировать класс с основными методами политики «CRUD», уже включенными в класс, вы можете указать при выполнении команды:make:policy
--model
php artisan make:policy PostPolicy --model=Post
Все политики разрешаются через служебный контейнер Laravel , что позволяет вам указывать любые необходимые зависимости в конструкторе политики, чтобы они автоматически вводились.
Регистрация политик
Как только политика существует, она должна быть зарегистрирована. В AuthServiceProvider
комплекте со свежими приложениями Laravel содержится policies
свойство, которое сопоставляет ваши модели Eloquent с соответствующими политиками. Регистрация политики укажет Laravel, какую политику использовать при авторизации действий для данной модели:
<?php
namespace App\Providers;
use App\Post;
use App\Policies\PostPolicy;
use Illuminate\Support\Facades\Gate;
use Illuminate\Foundation\Support\Providers\AuthServiceProvider as ServiceProvider;
class AuthServiceProvider extends ServiceProvider
{
/**
* The policy mappings for the application.
*
* @var array
*/
protected $policies = [
Post::class => PostPolicy::class,
];
/**
* Register any application authentication / authorization services.
*
* @return void
*/
public function boot()
{
$this->registerPolicies();
//
}
}
Автоопределение политики
Вместо ручной регистрации политик модели Laravel может автоматически обнаруживать политики, если модель и политика соответствуют стандартным соглашениям об именах Laravel. В частности, политики должны находиться в Policies
каталоге под каталогом, содержащим модели. Так, например, модели могут быть размещены в app
каталоге, в то время как политики могут быть размещены в каталоге. Кроме того, имя политики должно соответствовать названию модели и иметь суффикс. Таким образом, модель будет соответствовать классу.app/Policies
Policy
User
UserPolicy
Если вы хотите предоставить свою собственную логику обнаружения политики, вы можете зарегистрировать пользовательский обратный вызов, используя метод. Как правило, этот метод должен вызываться из метода вашего приложения :Gate::guessPolicyNamesUsing
boot
AuthServiceProvider
use Illuminate\Support\Facades\Gate;
Gate::guessPolicyNamesUsing(function ($modelClass) {
// return policy class name...
});
Любые политики, которые явно указаны в вашем документе,
AuthServiceProvider
будут иметь приоритет над любыми потенциальными автоматически обнаруженными политиками.
Написание политики
Методы политики
После регистрации политики вы можете добавить методы для каждого действия, которое она авторизует. Например, давайте определим update
метод для нашего, PostPolicy
который определяет, может ли данное User
лицо обновить данный Post
экземпляр.
update
Метод получит User
и в Post
экземпляре в качестве аргументов, и он должен возвращать true
или false
указание авторизовано ли пользователь обновить данными Post
. Итак, для этого примера давайте проверим, id
совпадает ли пользователь user_id
с постом:
<?php
namespace App\Policies;
use App\User;
use App\Post;
class PostPolicy
{
/**
* Determine if the given post can be updated by the user.
*
* @param \App\User $user
* @param \App\Post $post
* @return bool
*/
public function update(User $user, Post $post)
{
return $user->id === $post->user_id;
}
}
Вы можете продолжать определять дополнительные методы политики, необходимые для различных действий, которые она разрешает. Например, вы можете определить view
или delete
методы для авторизации различных Post
действий, но помните, что вы можете давать своим методам политики любое имя, которое вам нравится.
Если вы использовали
--model
параметр при создании вашей политики с помощью консоли Artisan, он уже будет содержать методы дляview
,create
,update
,delete
,restore
, иforceDelete
действия.
Методы без моделей
Некоторые методы политики получают только аутентифицированного пользователя, а не экземпляр модели, которую они авторизуют. Эта ситуация наиболее распространена при авторизации create
действий. Например, если вы создаете блог, вы можете проверить, имеет ли пользователь право создавать какие-либо сообщения вообще.
При определении методов политики, которые не будут получать экземпляр модели, например, create
метод, он не будет получать экземпляр модели. Вместо этого вы должны определить метод как ожидающий только аутентифицированного пользователя:
/**
* Determine if the given user can create posts.
*
* @param \App\User $user
* @return bool
*/
public function create(User $user)
{
//
}
Гостевые пользователи
По умолчанию все шлюзы и политики автоматически возвращаются, false
если входящий HTTP-запрос не был инициирован аутентифицированным пользователем. Однако вы можете разрешить этим проверкам авторизации проходить к вашим воротам и политикам, объявив «необязательный» тип-подсказку или предоставив null
значение по умолчанию для определения пользовательского аргумента:
<?php
namespace App\Policies;
use App\User;
use App\Post;
class PostPolicy
{
/**
* Determine if the given post can be updated by the user.
*
* @param \App\User $user
* @param \App\Post $post
* @return bool
*/
public function update(?User $user, Post $post)
{
return $user->id === $post->user_id;
}
}
Политические фильтры
Для определенных пользователей вы можете разрешить все действия в рамках данной политики. Для этого определите before
метод в политике. Этот before
метод будет выполняться перед любыми другими методами в политике, что даст вам возможность авторизовать действие до фактического вызова намеченного метода политики. Эта функция чаще всего используется для авторизации администраторов приложений для выполнения любых действий:
public function before($user, $ability)
{
if ($user->isSuperAdmin()) {
return true;
}
}
Если вы хотите запретить все авторизации для пользователя, вы должны вернуться false
из before
метода. Если null
возвращается, авторизация перейдет к методу политики.
before
Метод класса политики не будет вызываться , если класс не содержит метод с именем , совпадающим с именем способности проверяется.
Авторизация действий с использованием политик
Через модель пользователя
User
Модель , которая поставляется вместе с приложением Laravel включает в себя две полезные методы для санкционирования действий: can
а cant
. can
Метод получает действие , которое вы хотите разрешить и соответствующую модель. Например, давайте определим, авторизован ли пользователь для обновления данной Post
модели:
if ($user->can('update', $post)) {
//
}
Если для данной модели зарегистрирована политика , can
метод автоматически вызывает соответствующую политику и возвращает логический результат. Если для модели не зарегистрировано никакой политики, can
метод попытается вызвать основанный на Closure Gate, соответствующий данному имени действия.
Действия, которые не требуют моделей
Помните, что для некоторых действий create
может не потребоваться экземпляр модели. В этих ситуациях вы можете передать имя класса can
методу. Имя класса будет использоваться, чтобы определить, какую политику использовать при авторизации действия:
use App\Post;
if ($user->can('create', Post::class)) {
// Executes the "create" method on the relevant policy...
}
Через промежуточное ПО
Laravel включает промежуточное программное обеспечение, которое может авторизовать действия до того, как входящий запрос достигнет ваших маршрутов или контроллеров. По умолчанию промежуточному программному обеспечению назначается ключ в вашем классе. Давайте рассмотрим пример использования промежуточного программного обеспечения для авторизации того, что пользователь может обновлять запись в блоге:Illuminate\Auth\Middleware\Authorize
can
App\Http\Kernel
can
use App\Post;
Route::put('/post/{post}', function (Post $post) {
// The current user may update the post...
})->middleware('can:update,post');
В этом примере мы передаем can
промежуточному программному обеспечению два аргумента. Первый - это имя действия, которое мы хотим авторизовать, а второй - параметр маршрута, который мы хотим передать методу политики. В этом случае, поскольку мы используем неявное связывание модели , Post
модель будет передана методу политики. Если пользователь не авторизован для выполнения данного действия, 403
промежуточное программное обеспечение сгенерирует HTTP-ответ с кодом состояния.
Действия, которые не требуют моделей
Опять же, некоторые действия, такие как, create
могут не требовать экземпляра модели. В этих ситуациях вы можете передать имя класса промежуточному программному обеспечению. Имя класса будет использоваться, чтобы определить, какую политику использовать при авторизации действия:
Route::post('/post', function () {
// The current user may create posts...
})->middleware('can:create,App\Post');
Через помощников контроллера
В дополнение к полезным методам, предоставляемым для User
модели, Laravel предоставляет полезный authorize
метод для любого из ваших контроллеров, расширяющих базовый класс. Как и метод, этот метод принимает имя действия, которое вы хотите авторизовать, и соответствующую модель. Если действие не авторизовано, метод выдаст значение , которое обработчик исключений Laravel по умолчанию преобразует в HTTP-ответ с кодом состояния:App\Http\Controllers\Controller
can
authorize
Illuminate\Auth\Access\AuthorizationException
403
<?php
namespace App\Http\Controllers;
use App\Post;
use Illuminate\Http\Request;
use App\Http\Controllers\Controller;
class PostController extends Controller
{
/**
* Update the given blog post.
*
* @param Request $request
* @param Post $post
* @return Response
* @throws \Illuminate\Auth\Access\AuthorizationException
*/
public function update(Request $request, Post $post)
{
$this->authorize('update', $post);
// The current user can update the blog post...
}
}
Действия, которые не требуют моделей
Как обсуждалось ранее, некоторые действия, такие как, create
могут не требовать экземпляра модели. В этих ситуациях вы можете передать имя класса authorize
методу. Имя класса будет использоваться, чтобы определить, какую политику использовать при авторизации действия:
/**
* Create a new blog post.
*
* @param Request $request
* @return Response
* @throws \Illuminate\Auth\Access\AuthorizationException
*/
public function create(Request $request)
{
$this->authorize('create', Post::class);
// The current user can create blog posts...
}
Авторизация контроллеров ресурсов
Если вы используете контроллеры ресурсов , вы можете использовать authorizeResource
метод в конструкторе контроллера. Этот метод прикрепит соответствующее can
определение промежуточного программного обеспечения к методам контроллера ресурсов.
authorizeResource
Метод принимает имя класса модели в качестве первого аргумента, и имени маршрута / параметра запроса , который будет содержать идентификатор модели в качестве второго аргумента:
<?php
namespace App\Http\Controllers;
use App\Post;
use Illuminate\Http\Request;
use App\Http\Controllers\Controller;
class PostController extends Controller
{
public function __construct()
{
$this->authorizeResource(Post::class, 'post');
}
}
Вы можете использовать команду с возможностью быстро создать класс политики для данной модели: .
make:policy
--model
php artisan make:policy PostPolicy --model=Post
Шаблоны через клинок
При написании шаблонов Blade может потребоваться отобразить часть страницы, только если пользователь авторизован для выполнения определенного действия. Например, вы можете отобразить форму обновления для сообщения в блоге, только если пользователь действительно может обновить сообщение. В этой ситуации вы можете использовать @can
и @cannot
семейство директив:
@can('update', $post)
<!-- The Current User Can Update The Post -->
@elsecan('create', App\Post::class)
<!-- The Current User Can Create New Post -->
@endcan
@cannot('update', $post)
<!-- The Current User Can't Update The Post -->
@elsecannot('create', App\Post::class)
<!-- The Current User Can't Create New Post -->
@endcannot
Эти директивы являются удобными ярлыками для написания и заявлений. В и выше утверждении соответственно переводит на следующие утверждения:@if
@unless
@can
@cannot
@if (Auth::user()->can('update', $post))
<!-- The Current User Can Update The Post -->
@endif
@unless (Auth::user()->can('update', $post))
<!-- The Current User Can't Update The Post -->
@endunless
Действия, которые не требуют моделей
Как и большинство других методов авторизации, вы можете передать имя класса директивам @can
and, @cannot
если для действия не требуется экземпляр модели:
@can('create', App\Post::class)
<!-- The Current User Can Create Posts -->
@endcan
@cannot('create', App\Post::class)
<!-- The Current User Can't Create Posts -->
@endcannot
0 комментариев