1. Seguridad
  2. Autorización

Introducción

Además de proporcionar servicios de autenticación integrados, Laravel también proporciona una forma sencilla de autorizar acciones de usuario contra un recurso específico. Por ejemplo, aunque un usuario esté autenticado, es posible que no esté autorizado para actualizar o eliminar ciertos modelos Eloquent o registros de la base de datos gestionados por tu aplicación. Las funciones de autorización de Laravel proporcionan una forma fácil y organizada de gestionar este tipo de comprobaciones de autorización.

Laravel proporciona dos formas principales de autorizar acciones: gates y policies. Piensa en gates y policies como rutas y controladores. Los gates proporcionan un enfoque simple basado en cierres para la autorización, mientras que las policies, al igual que los controladores, agrupan la lógica en torno a un modelo o recurso específico. En esta documentación, exploraremos primero los gates y luego examinaremos las policies.

No necesitas elegir entre usar exclusivamente gates o policies al construir una aplicación. La mayoría de las aplicaciones probablemente contendrán una mezcla de gates y policies, ¡y eso está perfectamente bien! Los gates son más aplicables a acciones que no están relacionadas con ningún modelo o recurso, como ver un panel de administrador. En cambio, las policies deben usarse cuando deseas autorizar una acción para un modelo o recurso específico.

Gates

Escritura de gates

Advertencia Los gates son una excelente manera de aprender los conceptos básicos de las características de autorización de Laravel; sin embargo, al construir aplicaciones robustas con Laravel, deberías considerar usar policies para organizar tus reglas de autorización.

Los gates son simplemente cierres que determinan si un usuario está autorizado para realizar una acción determinada. Normalmente, los gates se definen dentro del método boot de la clase App\Providers\AuthServiceProvider utilizando la fachada Gate. Los gates siempre reciben una instancia de usuario como su primer argumento y opcionalmente pueden recibir argumentos adicionales, como un modelo Eloquent relevante.

En este ejemplo, definiremos un gate para determinar si un usuario puede actualizar un modelo App\Models\Post dado. El gate logrará esto comparando el id del usuario con el user_id del usuario que creó la publicación:

use App\Models\Post;
use App\Models\User;
use Illuminate\Support\Facades\Gate;
 
/**
* Registra cualquier servicio de autenticación/autorización.
*/
public function boot(): void
{
Gate::define('update-post', function (User $user, Post $post) {
return $user->id === $post->user_id;
});
}

Al igual que los controladores, los gates también se pueden definir mediante un array de devolución de llamada de clase:

use App\Policies\PostPolicy;
use Illuminate\Support\Facades\Gate;
 
/**
* Registra cualquier servicio de autenticación/autorización.
*/
public function boot(): void
{
Gate::define('update-post', [PostPolicy::class, 'update']);
}

Autorización de acciones

Para autorizar una acción mediante gates, debes utilizar los métodos allows o denies proporcionados por la fachada Gate. Ten en cuenta que no es necesario pasar el usuario actualmente autenticado a estos métodos. Laravel se encargará automáticamente de pasar el usuario al cierre del gate. Es típico llamar a los métodos de autorización del gate dentro de los controladores de tu aplicación antes de realizar una acción que requiera autorización:

<?php
 
namespace App\Http\Controllers;
 
use App\Http\Controllers\Controller;
use App\Models\Post;
use Illuminate\Http\RedirectResponse;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Gate;
 
class PostController extends Controller
{
/**
* Actualiza la publicación dada.
*/
public function update(Request $request, Post $post): RedirectResponse
{
if (! Gate::allows('update-post', $post)) {
abort(403);
}
 
// Actualizar la publicación...
 
return redirect('/posts');
}
}

Si deseas determinar si un usuario que no es el usuario autenticado actualmente está autorizado para realizar una acción, puedes usar el método forUser en la fachada Gate:

if (Gate::forUser($user)->allows('update-post', $post)) {
// El usuario puede actualizar la publicación...
}
 
if (Gate::forUser($user)->denies('update-post', $post)) {
// El usuario no puede actualizar la publicación...
}

Puedes autorizar múltiples acciones a la vez usando los métodos any o none:

if (Gate::any(['update-post', 'delete-post'], $post)) {
// El usuario puede actualizar o eliminar la publicación...
}
 
if (Gate::none(['update-post', 'delete-post'], $post)) {
// El usuario no puede actualizar o eliminar la publicación...
}

Autorización o lanzamiento de excepciones

Si deseas intentar autorizar una acción y lanzar automáticamente una excepción Illuminate\Auth\Access\AuthorizationException si el usuario no tiene permitido realizar la acción dada, puedes usar el método authorize de la fachada Gate. Las instancias de AuthorizationException se convierten automáticamente en una respuesta HTTP 403 por el manejador de excepciones de Laravel:

Gate::authorize('update-post', $post);
 
// La acción está autorizada...

Proporcionar un contexto adicional

Los métodos de gate para autorizar habilidades (allows, denies, check, any, none, authorize, can, cannot) y las directivas de autorización Blade (@can, @cannot, @canany) pueden recibir una matriz como segundo argumento. Estos elementos de la matriz se pasan como parámetros al cierre del gate y se pueden usar para obtener un contexto adicional al tomar decisiones de autorización:

use App\Models\Category;
use App\Models\User;
use Illuminate\Support\Facades\Gate;
 
Gate::define('create-post', function (User $user, Category $category, bool $pinned) {
if (! $user->canPublishToGroup($category->group)) {
return false;
} elseif ($pinned && ! $user->canPinPosts()) {
return false;
}
 
return true;
});
 
if (Gate::check('create-post', [$category, $pinned])) {
// El usuario puede crear la publicación...
}

Respuestas de gates

Hasta ahora, solo hemos examinado gates que devuelven valores booleanos simples. Sin embargo, a veces puedes desear devolver una respuesta más detallada, incluido un mensaje de error. Para hacerlo, puedes devolver una instancia de Illuminate\Auth\Access\Response desde tu gate:

use App\Models\User;
use Illuminate\Auth\Access\Response;
use Illuminate\Support\Facades\Gate;
 
Gate::define('edit-settings', function (User $user) {
return $user->isAdmin
? Response::allow()
: Response::deny('Debes ser un administrador.');
});

Incluso cuando devuelves una respuesta de autorización desde tu gate, el método Gate::allows seguirá devolviendo un valor booleano simple; sin embargo, puedes usar el método Gate::inspect para obtener la respuesta completa de autorización devuelta por el gate:

$response = Gate::inspect('edit-settings');
 
if ($response->allowed()) {
// La acción está autorizada...
} else {
echo $response->message();
}

Cuando usas el método Gate::authorize, que lanza una excepción AuthorizationException si la acción no está autorizada, el mensaje de error proporcionado por la respuesta de autorización se propagará a la respuesta HTTP:

Gate::authorize('edit-settings');
 
// La acción está autorizada...

Personalización del estado de respuesta HTTP

Cuando se niega una acción a través de un Gate, se devuelve una respuesta HTTP 403; sin embargo, a veces puede ser útil devolver un código de estado HTTP alternativo. Puedes personalizar el código de estado HTTP devuelto para una comprobación de autorización fallida utilizando el constructor estático denyWithStatus en la clase Illuminate\Auth\Access\Response:

use App\Models\User;
use Illuminate\Auth\Access\Response;
use Illuminate\Support\Facades\Gate;
 
Gate::define('edit-settings', function (User $user) {
return $user->isAdmin
? Response::allow()
: Response::denyWithStatus(404);
});

Debido a que ocultar recursos mediante una respuesta 404 es un patrón tan común para aplicaciones web, se ofrece el método denyAsNotFound para mayor comodidad:

use App\Models\User;
use Illuminate\Auth\Access\Response;
use Illuminate\Support\Facades\Gate;
 
Gate::define('edit-settings', function (User $user) {
return $user->isAdmin
? Response::allow()
: Response::denyAsNotFound();
});

Intercepción de verificaciones de gates

A veces, es posible que desees conceder todas las habilidades a un usuario específico. Puedes usar el método before para definir un cierre que se ejecute antes de todas las demás comprobaciones de autorización:

use App\Models\User;
use Illuminate\Support\Facades\Gate;
 
Gate::before(function (User $user, string $ability) {
if ($user->isAdministrator()) {
return true;
}
});

Si el cierre before devuelve un resultado no nulo, ese resultado se considerará el resultado de la comprobación de autorización.

Puedes usar el método after para definir un cierre que se ejecutará después de todas las demás comprobaciones de autorización:

use App\Models\User;
 
Gate::after(function (User $user, string $ability, bool|null $result, mixed $arguments) {
if ($user->isAdministrator()) {
return true;
}
});

Similar al método before, si el cierre after devuelve un resultado no nulo, ese resultado se considerará el resultado de la comprobación de autorización.

Autorización en línea

Ocasionalmente, es posible que desees determinar si el usuario autenticado actualmente está autorizado para realizar una acción determinada sin escribir un gate dedicado que corresponda a la acción. Laravel te permite realizar este tipo de comprobaciones de autorización "en línea" mediante los métodos Gate::allowIf y Gate::denyIf:

use App\Models\User;
use Illuminate\Support\Facades\Gate;
 
Gate::allowIf(fn (User $user) => $user->isAdministrator());
 
Gate::denyIf(fn (User $user) => $user->banned());

Si la acción no está autorizada o si no hay un usuario autenticado actualmente, Laravel lanzará automáticamente una excepción Illuminate\Auth\Access\AuthorizationException. Las instancias de AuthorizationException se convierten automáticamente en una respuesta HTTP 403 por el manejador de excepciones de Laravel.

Creación de políticas

Generación de políticas

Las políticas son clases que organizan la lógica de autorización en torno a un modelo o recurso en particular. Por ejemplo, si tu aplicación es un blog, es posible que tengas un modelo App\Models\Post y una política correspondiente App\Policies\PostPolicy para autorizar acciones de usuario, como crear o actualizar publicaciones.

Puedes generar una política usando el comando Artisan make:policy. La política generada se colocará en el directorio app/Policies. Si este directorio no existe en tu aplicación, Laravel lo creará por ti:

php artisan make:policy PostPolicy

El comando make:policy generará una clase de política vacía. Si deseas generar una clase con métodos de política de ejemplo relacionados con ver, crear, actualizar y eliminar el recurso, puedes proporcionar una opción --model al ejecutar el comando:

php artisan make:policy PostPolicy --model=Post

Registro de políticas

Una vez que se haya creado la clase de política, necesita registrarse. El registro de políticas es la forma en que podemos informar a Laravel qué política usar al autorizar acciones contra un tipo de modelo dado.

El App\Providers\AuthServiceProvider incluido en las aplicaciones Laravel nuevas contiene una propiedad policies que asigna tus modelos Eloquent a sus respectivas políticas. Registrar una política instruirá a Laravel sobre qué política utilizar al autorizar acciones contra un modelo Eloquent dado:

<?php
 
namespace App\Providers;
 
use App\Models\Post;
use App\Policies\PostPolicy;
use Illuminate\Foundation\Support\Providers\AuthServiceProvider as ServiceProvider;
use Illuminate\Support\Facades\Gate;
 
class AuthServiceProvider extends ServiceProvider
{
/**
* Las asignaciones de políticas para la aplicación.
*
* @var array
*/
protected $policies = [
Post::class => PostPolicy::class,
];
 
/**
* Registra cualquier servicio de autenticación/autorización de la aplicación.
*/
public function boot(): void
{
// ...
}
}

Auto-descubrimiento de políticas

En lugar de registrar manualmente las políticas de modelo, Laravel puede descubrir automáticamente las políticas siempre que el modelo y la política sigan las convenciones de nomenclatura estándar de Laravel. Específicamente, las políticas deben estar en un directorio Policies en o por encima del directorio que contiene tus modelos. Por ejemplo, los modelos pueden ubicarse en el directorio app/Models, mientras que las políticas pueden ubicarse en el directorio app/Policies. En esta situación, Laravel verificará las políticas en app/Models/Policies y luego app/Policies. Además, el nombre de la política debe coincidir con el nombre del modelo y tener un sufijo Policy. Así, una clase User del modelo correspondería a una clase de política UserPolicy.

Si deseas definir tu propia lógica de descubrimiento de políticas, puedes registrar un callback de descubrimiento de políticas personalizado utilizando el método Gate::guessPolicyNamesUsing. Por lo general, este método debe llamarse desde el método boot del AuthServiceProvider de tu aplicación:

use Illuminate\Support\Facades\Gate;
 
Gate::guessPolicyNamesUsing(function (string $modelClass) {
// Devuelve el nombre de la clase de política para el modelo dado...
});

Advertencia Cualquier política que esté explícitamente asignada en tu AuthServiceProvider tomará precedencia sobre cualquier política que se descubra automáticamente.

Escritura de políticas

Métodos de política

Una vez que la clase de política haya sido registrada, puedes agregar métodos para cada acción que autoriza. Por ejemplo, definamos un método update en nuestra PostPolicy que determine si un App\Models\User dado puede actualizar una instancia dada de App\Models\Post.

El método update recibirá como argumentos una instancia de User y una de Post, y debería devolver true o false indicando si el usuario está autorizado para actualizar la Post dada. Entonces, en este ejemplo, verificaremos que el id del usuario coincida con el user_id en la publicación:

<?php
 
namespace App\Policies;
 
use App\Models\Post;
use App\Models\User;
 
class PostPolicy
{
/**
* Determina si el usuario dado puede actualizar la publicación.
*/
public function update(User $user, Post $post): bool
{
return $user->id === $post->user_id;
}
}

Puedes seguir definiendo métodos adicionales en la política según sea necesario para las diversas acciones que autoriza. Por ejemplo, podrías definir métodos view o delete para autorizar varias acciones relacionadas con Post, pero recuerda que eres libre de darle a tus métodos de política el nombre que desees.

Si usaste la opción --model al generar tu política a través de la consola Artisan, ya contendrá métodos para las acciones viewAny, view, create, update, delete, restore y forceDelete.

Nota Todas las políticas se resuelven a través del contenedor de servicios de Laravel, lo que te permite sugerir dependencias necesarias en el constructor de la política para que se inyecten automáticamente.

Respuestas de políticas

Hasta ahora, solo hemos examinado métodos de política que devuelven valores booleanos simples. Sin embargo, a veces puedes desear devolver una respuesta más detallada, incluido un mensaje de error. Para hacerlo, puedes devolver una instancia de Illuminate\Auth\Access\Response desde tu método de política:

use App\Models\Post;
use App\Models\User;
use Illuminate\Auth\Access\Response;
 
/**
* Determina si el usuario dado puede actualizar la publicación.
*/
public function update(User $user, Post $post): Response
{
return $user->id === $post->user_id
? Response::allow()
: Response::deny('No eres el propietario de esta publicación.');
}

Cuando devuelves una respuesta de autorización desde tu política, el método Gate::allows seguirá devolviendo un valor booleano simple; sin embargo, puedes usar el método Gate::inspect para obtener la respuesta completa de autorización devuelta por el gate:

use Illuminate\Support\Facades\Gate;
 
$response = Gate::inspect('update', $post);
 
if ($response->allowed()) {
// La acción está autorizada...
} else {
echo $response->message();
}

Cuando usas el método Gate::authorize, que lanza una excepción AuthorizationException si la acción no está autorizada, el mensaje de error proporcionado por la respuesta de autorización se propagará a la respuesta HTTP:

Gate::authorize('update', $post);
 
// La acción está autorizada...

Personalización del estado de respuesta HTTP

Cuando se deniega una acción a través de un método de política, se devuelve una respuesta HTTP 403; sin embargo, a veces puede ser útil devolver un código de estado HTTP alternativo. Puedes personalizar el código de estado HTTP devuelto para una comprobación de autorización fallida utilizando el constructor estático denyWithStatus en la clase Illuminate\Auth\Access\Response:

use App\Models\Post;
use App\Models\User;
use Illuminate\Auth\Access\Response;
 
/**
* Determina si el usuario dado puede actualizar la publicación.
*/
public function update(User $user, Post $post): Response
{
return $user->id === $post->user_id
? Response::allow()
: Response::denyWithStatus(404);
}

Debido a que ocultar recursos mediante una respuesta 404 es un patrón tan común para aplicaciones web, se ofrece el método denyAsNotFound para mayor comodidad:

use App\Models\Post;
use App\Models\User;
use Illuminate\Auth\Access\Response;
 
/**
* Determina si el usuario dado puede actualizar la publicación.
*/
public function update(User $user, Post $post): Response
{
return $user->id === $post->user_id
? Response::allow()
: Response::denyAsNotFound();
}

Métodos sin modelos

Algunos métodos de política solo reciben una instancia del usuario actualmente autenticado. Esta situación es más común al autorizar acciones de create. Por ejemplo, si estás creando un blog, es posible que desees determinar si un usuario está autorizado para crear cualquier publicación en absoluto. En estas situaciones, tu método de política debería esperar recibir solo una instancia de usuario:

/**
* Determina si el usuario dado puede crear publicaciones.
*/
public function create(User $user): bool
{
return $user->role == 'writer';
}

Usuarios invitados

De forma predeterminada, todos los gates y las políticas devuelven automáticamente false si la solicitud HTTP entrante no fue iniciada por un usuario autenticado. Sin embargo, puedes permitir que estas comprobaciones de autorización pasen a través de tus gates y políticas declarando un tipo de declaración "opcional" o proporcionando un valor predeterminado null para la definición del argumento de usuario:

<?php
 
namespace App\Policies;
 
use App\Models\Post;
use App\Models\User;
 
class PostPolicy
{
/**
* Determina si el usuario dado puede actualizar la publicación.
*/
public function update(?User $user, Post $post): bool
{
return $user?->id === $post->user_id;
}
}

Filtros de políticas

Para ciertos usuarios, es posible que desees autorizar todas las acciones dentro de una política dada. Para lograr esto, define un método before en la política. El método before se ejecutará antes que cualquier otro método en la política, dándote la oportunidad de autorizar la acción antes de que se llame al método de política previsto. Esta función se utiliza comúnmente para autorizar a los administradores de la aplicación para realizar cualquier acción:

use App\Models\User;
 
/**
* Realiza comprobaciones de preautorización.
*/
public function before(User $user, string $ability): bool|null
{
if ($user->isAdministrator()) {
return true;
}
 
return null;
}

Si deseas denegar todas las comprobaciones de autorización para un tipo de usuario en particular, puedes devolver false desde el método before. Si se devuelve null, la comprobación de autorización pasará al método de política.

Advertencia El método before de una clase de política no se llamará si la clase no contiene un método con un nombre que coincida con el nombre de la capacidad que se está comprobando.

Autorización de acciones mediante políticas

A través del modelo de usuario

El modelo App\Models\User que se incluye en tu aplicación Laravel incluye dos métodos útiles para autorizar acciones: can y cannot. Los métodos can y cannot reciben el nombre de la acción que deseas autorizar y el modelo relevante. Por ejemplo, determinemos si un usuario está autorizado para actualizar un modelo App\Models\Post. Por lo general, esto se hará dentro de un método del controlador:

<?php
 
namespace App\Http\Controllers;
 
use App\Http\Controllers\Controller;
use App\Models\Post;
use Illuminate\Http\RedirectResponse;
use Illuminate\Http\Request;
 
class PostController extends Controller
{
/**
* Actualiza la publicación dada.
*/
public function update(Request $request, Post $post): RedirectResponse
{
if ($request->user()->cannot('update', $post)) {
abort(403);
}
 
// Actualizar la publicación...
 
return redirect('/posts');
}
}

Si se registra una política para el modelo dado, el método can llamará automáticamente a la política adecuada y devolverá el resultado booleano. Si no se registra ninguna política para el modelo, el método can intentará llamar al gate basado en cierres que coincida con el nombre de la acción dado.

Acciones que no requieren modelos

Recuerda, algunas acciones pueden corresponder a métodos de política como create que no requieren una instancia de modelo. En estas situaciones, puedes pasar un nombre de clase al método can. El nombre de la clase se utilizará para determinar qué política usar al autorizar la acción:

<?php
 
namespace App\Http\Controllers;
 
use App\Http\Controllers\Controller;
use App\Models\Post;
use Illuminate\Http\RedirectResponse;
use Illuminate\Http\Request;
 
class PostController extends Controller
{
/**
* Crea una publicación.
*/
public function store(Request $request): RedirectResponse
{
if ($request->user()->cannot('create', Post::class)) {
abort(403);
}
 
// Crear la publicación...
 
return redirect('/posts');
}
}

A través de los ayudantes del controlador

Además de los métodos útiles proporcionados al modelo App\Models\User, Laravel proporciona un útil método authorize a cualquiera de tus controladores que extiendan la clase base App\Http\Controllers\Controller.

Al igual que el método can, este método acepta el nombre de la acción que deseas autorizar y el modelo relevante. Si la acción no está autorizada, el método authorize lanzará una excepción Illuminate\Auth\Access\AuthorizationException que el gestor de excepciones de Laravel convertirá automáticamente en una respuesta HTTP con un código de estado 403:

<?php
 
namespace App\Http\Controllers;
 
use App\Http\Controllers\Controller;
use App\Models\Post;
use Illuminate\Http\RedirectResponse;
use Illuminate\Http\Request;
 
class PostController extends Controller
{
/**
* Actualiza la publicación de blog dada.
*
* @throws \Illuminate\Auth\Access\AuthorizationException
*/
public function update(Request $request, Post $post): RedirectResponse
{
$this->authorize('update', $post);
 
// El usuario actual puede actualizar la publicación del blog...
 
return redirect('/posts');
}
}

Acciones que no requieren modelos

Como se discutió anteriormente, algunos métodos de política como create no requieren una instancia de modelo. En estas situaciones, debes pasar un nombre de clase al método authorize. El nombre de la clase se utilizará para determinar qué política usar al autorizar la acción:

use App\Models\Post;
use Illuminate\Http\RedirectResponse;
use Illuminate\Http\Request;
 
/**
* Crea una nueva publicación de blog.
*
* @throws \Illuminate\Auth\Access\AuthorizationException
*/
public function create(Request $request): RedirectResponse
{
$this->authorize('create', Post::class);
 
// El usuario actual puede crear publicaciones de blog...
 
return redirect('/posts');
}

Autorización de controladores de recursos

Si estás utilizando controladores de recursos, puedes hacer uso del método authorizeResource en el constructor de tu controlador. Este método adjuntará las definiciones de middleware can apropiadas a los métodos del controlador de recursos.

El método authorizeResource acepta el nombre de clase del modelo como su primer argumento y el nombre del parámetro de ruta / solicitud que contendrá el ID del modelo como su segundo argumento. Debes asegurarte de que tu controlador de recursos se cree utilizando la bandera --model para que tenga las firmas de método y las sugerencias de tipo requeridas:

<?php
 
namespace App\Http\Controllers;
 
use App\Http\Controllers\Controller;
use App\Models\Post;
 
class PostController extends Controller
{
/**
* Crea una instancia del controlador.
*/
public function __construct()
{
$this->authorizeResource(Post::class, 'post');
}
}

Los siguientes métodos del controlador se asignarán a su método de política correspondiente. Cuando las solicitudes se dirijan al método del controlador dado, el método de política correspondiente se invocará automáticamente antes de que se ejecute el método del controlador:

Método del Controlador Método de la Política
index viewAny
show view
create create
store create
edit update
update update
destroy delete

Nota Puedes usar el comando make:policy con la opción --model para generar rápidamente una clase de política para un modelo dado: php artisan make:policy PostPolicy --model=Post.

A través de middleware

Laravel incluye un middleware que puede autorizar acciones antes de que la solicitud entrante llegue a tus rutas o controladores. De forma predeterminada, el middleware Illuminate\Auth\Middleware\Authorize se asigna a la clave can en tu clase App\Http\Kernel. Veamos un ejemplo de cómo usar el middleware can para autorizar que un usuario puede actualizar una publicación:

use App\Models\Post;
 
Route::put('/post/{post}', function (Post $post) {
// El usuario actual puede actualizar la publicación...
})->middleware('can:update,post');

En este ejemplo, estamos pasando al middleware can dos argumentos. El primero es el nombre de la acción que deseamos autorizar y el segundo es el parámetro de ruta que deseamos pasar al método de la política. En este caso, dado que estamos utilizando enlace implícito de modelos, se pasará un modelo App\Models\Post al método de la política. Si el usuario no está autorizado para realizar la acción dada, el middleware devolverá una respuesta HTTP con un código de estado 403.

Para mayor comodidad, también puedes adjuntar el middleware can a tu ruta utilizando el método can:

use App\Models\Post;
 
Route::put('/post/{post}', function (Post $post) {
// El usuario actual puede actualizar la publicación...
})->can('update', 'post');

Acciones que no requieren modelos

Nuevamente, algunos métodos de política como create no requieren una instancia de modelo. En estas situaciones, puedes pasar un nombre de clase al middleware. El nombre de la clase se utilizará para determinar qué política usar al autorizar la acción:

Route::post('/post', function () {
// El usuario actual puede crear publicaciones...
})->middleware('can:create,App\Models\Post');

Especificar el nombre completo de la clase dentro de una definición de middleware de cadena puede volverse engorroso. Por esa razón, puedes optar por adjuntar el middleware can a tu ruta utilizando el método can:

use App\Models\Post;
 
Route::post('/post', function () {
// El usuario actual puede crear publicaciones...
})->can('create', Post::class);

A través de plantillas Blade

Al escribir plantillas Blade, es posible que desees mostrar una parte de la página solo si el usuario está autorizado para realizar una acción determinada. Por ejemplo, es posible que desees mostrar un formulario de actualización para una publicación de blog solo si el usuario realmente puede actualizar la publicación. En esta situación, puedes usar las directivas @can y @cannot:

@can('update', $post)
<!-- El usuario actual puede actualizar la publicación... -->
@elsecan('create', App\Models\Post::class)
<!-- El usuario actual puede crear nuevas publicaciones... -->
@else
<!-- ... -->
@endcan
 
@cannot('update', $post)
<!-- El usuario actual no puede actualizar la publicación... -->
@elsecannot('create', App\Models\Post::class)
<!-- El usuario actual no puede crear nuevas publicaciones... -->
@endcannot

Estas directivas son accesos directos convenientes para escribir declaraciones @if y @unless. Las declaraciones @can y @cannot anteriores son equivalentes a las siguientes declaraciones:

@if (Auth::user()->can('update', $post))
<!-- El usuario actual puede actualizar la publicación... -->
@endif
 
@unless (Auth::user()->can('update', $post))
<!-- El usuario actual no puede actualizar la publicación... -->
@endunless

También puedes determinar si un usuario está autorizado para realizar cualquier acción desde una matriz de acciones dada. Para lograr esto, utiliza la directiva @canany:

@canany(['update', 'view', 'delete'], $post)
<!-- El usuario actual puede actualizar, ver o eliminar la publicación... -->
@elsecanany(['create'], \App\Models\Post::class)
<!-- El usuario actual puede crear una publicación... -->
@endcanany

Acciones que no requieren modelos

Al igual que con la mayoría de los otros métodos de autorización, puedes pasar un nombre de clase a las directivas @can y @cannot si la acción no requiere una instancia de modelo:

@can('create', App\Models\Post::class)
<!-- El usuario actual puede crear publicaciones... -->
@endcan
 
@cannot('create', App\Models\Post::class)
<!-- El usuario actual no puede crear publicaciones... -->
@endcannot

Proporcionar un contexto adicional

Al autorizar acciones mediante políticas, puedes pasar una matriz como segundo argumento a las diversas funciones y ayudantes de autorización. El primer elemento en la matriz se utilizará para determinar qué política se debe invocar, mientras que el resto de los elementos de la matriz se pasan como parámetros al método de la política y se pueden utilizar para obtener contexto adicional al tomar decisiones de autorización. Por ejemplo, considera el siguiente método de definición de la política PostPolicy que contiene un parámetro adicional $category:

/**
* Determina si el usuario dado puede actualizar la publicación.
*/
public function update(User $user, Post $post, int $category): bool
{
return $user->id === $post->user_id &&
$user->canUpdateCategory($category);
}

Cuando intentas determinar si el usuario autenticado puede actualizar una publicación dada, puedes invocar este método de política de la siguiente manera:

/**
* Actualiza la publicación de blog dada.
*
* @throws \Illuminate\Auth\Access\AuthorizationException
*/
public function update(Request $request, Post $post): RedirectResponse
{
$this->authorize('update', [$post, $request->category]);
 
// El usuario actual puede actualizar la publicación del blog...
 
return redirect('/posts');
}