Laravel
Tutorial Laravel: Autorización (Policies y Gates)
Laravel y sus fundamentos de autorización permiten controlar acciones basadas en roles y permisos utilizando gates y policies. Aprende cómo aplicarlo.
Aprende Laravel GRATIS y certifícateFundamentos de autorización en Laravel
En Laravel, la autorización es el proceso que determina si un usuario autenticado tiene permiso para realizar una acción específica. Mientras que la autenticación verifica la identidad del usuario, la autorización controla el acceso a recursos y operaciones dentro de la aplicación.
Laravel ofrece un sistema de autorización sencillo y robusto que permite definir políticas de acceso de manera flexible. Este sistema facilita el control granular sobre quién puede realizar qué acciones, basándose en roles, permisos o cualquier otra lógica personalizada que se requiera.
El núcleo de la autorización en Laravel se basa en dos componentes principales: Gates y Policies. Las Gates son funciones sencillas que determinan si un usuario está autorizado para realizar una acción, mientras que las Policies son clases organizadas que agrupan métodos de autorización relacionados con un modelo específico.
Para implementar la autorización, es fundamental comprender cómo Laravel utiliza el proveedor de autenticación para obtener la información del usuario y cómo esa información se emplea en las Gates y Policies para evaluar permisos. Esto permite crear reglas de autorización que pueden ser aplicadas tanto en los controladores como directamente en las vistas.
Un ejemplo básico de autorización en una ruta podría ser:
use Illuminate\Support\Facades\Gate;
Route::get('/admin', function () {
if (Gate::allows('acceder-admin')) {
// El usuario está autorizado
} else {
// El usuario no está autorizado
}
});
En este fragmento, se utiliza la facade Gate para verificar si el usuario actual tiene permiso para acceder a la sección administrativa.
Además, Laravel proporciona diversos helpers y directivas de Blade para facilitar la implementación de la autorización en las vistas. Por ejemplo, la directiva @can
permite mostrar contenido únicamente a usuarios autorizados:
@can('editar-publicacion', $publicacion)
<!-- Contenido para editar la publicación -->
@endcan
Es importante destacar que la autorización puede basarse en diferentes criterios, como las propiedades del usuario, relaciones con otros modelos o incluso condiciones temporales. Esto brinda una gran flexibilidad para satisfacer las necesidades específicas de cada aplicación.
Para asegurar una gestión eficiente de los permisos, es recomendable estructurar las reglas de autorización de manera coherente y mantener el código organizado. Esto facilita el mantenimiento y la escalabilidad de la aplicación a medida que crece en complejidad.
Definición y uso de Gates
Las Gates en Laravel son funciones de autorización que permiten determinar si un usuario tiene permiso para realizar una acción específica. A diferencia de las Policies, que están asociadas a un modelo, las Gates son ideales para verificaciones más simples o que no están relacionadas directamente con un modelo en particular.
Definiendo Gates
Para definir una Gate, se utiliza el método Gate::define
en el método boot
de la clase AuthServiceProvider
. Este método acepta un nombre para la gate y una función de callback que contiene la lógica de autorización.
Por ejemplo, para definir una gate que verifica si un usuario es administrador:
<?php
namespace App\Providers;
use Illuminate\Support\Facades\Gate;
use Illuminate\Foundation\Support\Providers\AuthServiceProvider as ServiceProvider;
class AuthServiceProvider extends ServiceProvider
{
public function boot()
{
Gate::define('acceder-admin', function ($user) {
return $user->esAdministrador();
});
}
}
En este ejemplo, la Gate acceder-admin
evalúa si el método esAdministrador()
del usuario autenticado devuelve true
.
Utilizando Gates en controladores
Una vez definida la gate, se puede utilizar en los controladores para autorizar acciones. Se emplea el facade Gate
y los métodos allows
o denies
.
Por ejemplo:
use Illuminate\Support\Facades\Gate;
public function accederAreaAdmin()
{
if (Gate::allows('acceder-admin')) {
// El usuario tiene permiso para acceder
return view('admin.dashboard');
} else {
// El usuario no tiene permiso
abort(403, 'Acceso no autorizado');
}
}
En este fragmento, se verifica si el usuario actual tiene permiso para acceder al área de administración y, en caso contrario, se retorna un error 403.
Utilizando Gates en vistas
En las vistas Blade, Laravel proporciona la directiva @can
para facilitar la verificación de permisos mediante Gates:
@can('acceder-admin')
<!-- Contenido visible solo para administradores -->
<a href="{{ route('admin.configuracion') }}">Configuración</a>
@endcan
También se puede usar la directiva @cannot
para el caso opuesto:
@cannot('acceder-admin')
<!-- Contenido para usuarios no administradores -->
<p>No tienes acceso a las opciones de administración.</p>
@endcannot
Estas directivas mejoran la legibilidad del código y permiten un control preciso sobre lo que se muestra al usuario.
Pasando parámetros a las Gates
Las Gates pueden aceptar parámetros adicionales, lo que es útil para decisiones de autorización más complejas. Por ejemplo, si se desea verificar si un usuario puede editar un determinado post:
Gate::define('editar-post', function ($user, $post) {
return $user->id === $post->autor_id;
});
En este caso, la Gate editar-post
compara el ID del usuario autenticado con el ID del autor del post.
Para utilizar esta gate en un controlador:
public function editar(Post $post)
{
if (Gate::denies('editar-post', $post)) {
abort(403, 'No estás autorizado para editar este post');
}
// Lógica para editar el post
}
Y en una vista Blade:
@can('editar-post', $post)
<!-- Enlace para editar el post -->
<a href="{{ route('posts.editar', $post) }}">Editar</a>
@endcan
Autorización de ccciones específicas
Las Gates también pueden utilizarse para autorizar acciones específicas de manera global. Por ejemplo, si se desea controlar el acceso a una funcionalidad en mantenimiento:
Gate::define('acceso-funcionalidad-x', function ($user) {
return $user->tienePermisoEspecial();
});
Luego, en cualquier parte de la aplicación, se puede verificar este permiso:
if (Gate::allows('acceso-funcionalidad-x')) {
// Permitir acceso a la funcionalidad
} else {
// Mostrar mensaje de mantenimiento
}
Utilizando policy methods como Gates
Laravel permite utilizar métodos de Policy como si fueran Gates mediante el método Gate::define
. Esto puede ser útil para reutilizar lógica de autorización existente.
Gate::define('ver-reporte', 'App\Policies\ReportePolicy@ver');
De esta forma, se define una Gate ver-reporte
que utiliza el método ver
de ReportePolicy
.
Reglas de prioridad y before hooks
Es posible definir una regla general que se evalúe antes que cualquier otra Gate mediante el método before
:
Gate::before(function ($user, $ability) {
if ($user->esSuperAdmin()) {
return true;
}
});
Con este hook, si el usuario es superadministrador, se le concederá acceso a todas las acciones sin evaluar las demás Gates.
Listado de habilidades disponibles
Para obtener un listado de todas las habilidades (abilities) definidas en las Gates, se puede acceder a través de:
$habilidades = Gate::abilities();
Esto es útil para generar dinámicamente interfaces de administración de permisos o para propósitos de depuración.
Buenas prácticas con Gates:
- Mantener simplicidad: Utilizar Gates para casos simples y Policies para lógica más compleja o relacionada con modelos.
- Nombres descriptivos: Asignar nombres claros y significativos a las Gates para mejorar la legibilidad.
- Evitar redundancia: No duplicar lógica entre Gates y Policies; reutilizar código siempre que sea posible.
- Centralizar definiciones: Definir todas las Gates en el
AuthServiceProvider
para mantener una estructura organizada.
Las Gates proporcionan una forma eficiente y flexible de manejar la autorización en Laravel, permitiendo controlar el acceso a diversas partes de la aplicación de manera sencilla y coherente.
Creación y uso de Policies
En Laravel, las Policies son clases dedicadas a organizar la lógica de autorización relacionada con un modelo específico. Esto permite definir de forma estructurada quién puede realizar ciertas acciones sobre las entidades de la aplicación, mejorando la mantenibilidad y claridad del código.
Para crear una Policy, Laravel proporciona el comando Artisan make:policy
. Por ejemplo, para generar una Policy para el modelo Post
, se ejecuta:
php artisan make:policy PostPolicy --model=Post
Este comando genera la clase PostPolicy
dentro del directorio app/Policies
, preconfigurada para el modelo indicado. La opción --model=Post
asocia directamente la Policy con el modelo Post
, facilitando su integración.
La Policy generada contiene métodos correspondientes a las diferentes acciones que se pueden realizar sobre el modelo. Un ejemplo básico de la clase PostPolicy
es:
<?php
namespace App\Policies;
use App\Models\User;
use App\Models\Post;
class PostPolicy
{
public function viewAny(User $user)
{
// Determina si el usuario puede ver cualquier Post
}
public function view(User $user, Post $post)
{
// Determina si el usuario puede ver un Post específico
}
public function create(User $user)
{
// Determina si el usuario puede crear un Post
}
public function update(User $user, Post $post)
{
// Determina si el usuario puede actualizar un Post
}
public function delete(User $user, Post $post)
{
// Determina si el usuario puede eliminar un Post
}
// Otros métodos personalizados
}
Cada método recibe como parámetros al usuario autenticado y, en caso necesario, la instancia del modelo relevante. Dentro de estos métodos se implementa la lógica que determina si el usuario tiene permiso para realizar la acción especificada.
Por ejemplo, para permitir que solo el autor pueda actualizar su propio post:
public function update(User $user, Post $post)
{
return $user->id === $post->author_id;
}
Una vez definidas las Policies, es esencial registrarlas en el AuthServiceProvider
para que Laravel las reconozca. Esto se hace agregando la Policy al array $policies
de la siguiente manera:
protected $policies = [
Post::class => PostPolicy::class,
];
Este registro vincula el modelo Post
con la PostPolicy
, permitiendo a Laravel resolver automáticamente qué Policy aplicar en cada caso.
Para utilizar las Policies en los controladores, se puede emplear el método authorize
proporcionado por el trait AuthorizesRequests
. Por ejemplo:
public function edit(Post $post)
{
$this->authorize('update', $post);
// Lógica para mostrar el formulario de edición
}
Aquí, se verifica si el usuario está autorizado para actualizar el post antes de proceder. Si no tiene permiso, Laravel lanzará una excepción de autorización, evitando el acceso no autorizado.
También es posible realizar comprobaciones de autorización utilizando el método can
del usuario autenticado:
if (auth()->user()->can('delete', $post)) {
// El usuario puede eliminar el post
} else {
// Acceso denegado
}
En las vistas Blade, las Policies se pueden aplicar mediante las directivas @can
y @cannot
, lo que facilita el control de la presentación del contenido según los permisos del usuario:
@can('update', $post)
<a href="{{ route('posts.edit', $post) }}">Editar</a>
@endcan
Estos helpers mejoran la legibilidad del código y permiten mantener una lógica de autorización consistente en toda la aplicación.
Las Policies también admiten la definición de un método before
, que se ejecuta antes de los demás métodos de autorización. Esto es útil para otorgar permisos globales a ciertos usuarios, como administradores:
public function before(User $user, $ability)
{
if ($user->isAdmin()) {
return true;
}
}
Con este enfoque, si el método isAdmin()
devuelve true
, el usuario tendrá permiso para todas las acciones sin necesidad de evaluar los demás métodos de la Policy.
Además de los métodos predefinidos, es posible agregar métodos personalizados según las necesidades de la aplicación. Por ejemplo, si se requiere una acción para restaurar un post:
public function restore(User $user, Post $post)
{
return $user->id === $post->author_id && $post->trashed();
}
Esta flexibilidad permite adaptar las Policies a casos de uso específicos, manteniendo la lógica de autorización centralizada y coherente.
Para aplicar las Policies de forma automática en los controladores de recursos, se puede utilizar el método authorizeResource
en el constructor del controlador:
public function __construct()
{
$this->authorizeResource(Post::class, 'post');
}
De esta manera, Laravel aplicará las reglas de autorización correspondientes en cada acción del controlador, basándose en las convenciones establecidas.
En resumen, las Policies proporcionan una forma estructurada y robusta de manejar la autorización en Laravel, facilitando el mantenimiento y la escalabilidad de las aplicaciones. Al centralizar la lógica de permisos, se mejora la seguridad y se simplifica la gestión de accesos en proyectos complejos.
Aplicación de Policies en controladores y vistas
Una vez definidas y registradas las Policies, es fundamental aplicarlas correctamente en los controladores y vistas para garantizar la seguridad y control de acceso en la aplicación. Laravel proporciona diversas formas de integrar las policies en estos componentes de manera eficiente.
Uso de Policies en controladores
Para autorizar acciones en un controlador, se utiliza el método authorize
proporcionado por el trait AuthorizesRequests
. Este método facilita la verificación de permisos antes de ejecutar la lógica del controlador.
Ejemplo de autorización en un método de controlador:
namespace App\Http\Controllers;
use App\Models\Post;
class PostController extends Controller
{
public function edit(Post $post)
{
$this->authorize('update', $post);
// Lógica para mostrar el formulario de edición
return view('posts.edit', compact('post'));
}
public function destroy(Post $post)
{
$this->authorize('delete', $post);
// Lógica para eliminar el post
$post->delete();
return redirect()->route('posts.index')->with('status', 'Post eliminado correctamente');
}
}
En este ejemplo:
- Se utiliza
$this->authorize('update', $post);
para verificar si el usuario autenticado tiene permiso para actualizar el post. - Si la autorización falla, Laravel lanza una excepción
AuthorizationException
, que por defecto retorna una respuesta 403. - La misma lógica se aplica para la eliminación del post con
$this->authorize('delete', $post);
.
Autorización automática en controladores de recursos
Laravel permite aplicar la autorización de forma automática en controladores de recursos utilizando el método authorizeResource
en el constructor del controlador.
Implementación de autorización automática:
public function __construct()
{
$this->authorizeResource(Post::class, 'post');
}
Con esta configuración:
- Laravel invoca automáticamente los métodos correspondientes de la Policy antes de ejecutar las acciones estándar del controlador de recursos (
index
,show
,create
,store
,edit
,update
,destroy
). - El segundo parámetro
'post'
indica el nombre de la variable de ruta que contiene la instancia del modelo.
Consideraciones importantes:
- Asegúrese de que las rutas estén definidas correctamente y usen los nombres de parámetros esperados.
- Para acciones personalizadas, deberá realizar la autorización manualmente con
$this->authorize()
.
Uso del middleware can
Otra forma de aplicar las Policies es mediante el uso del middleware can
en las rutas o en el constructor del controlador.
Aplicación del middleware en rutas:
Route::get('/posts/{post}/edit', [PostController::class, 'edit'])
->middleware('can:update,post');
Aplicación del middleware en el constructor del controlador:
public function __construct()
{
$this->middleware('can:update,post')->only('edit', 'update');
$this->middleware('can:delete,post')->only('destroy');
}
Con el middleware can
:
- Se verifica la autorización antes de ejecutar el método del controlador.
- Si el usuario no está autorizado, se lanza una excepción automáticamente.
Uso de Policies en vistas Blade
En las vistas, Laravel ofrece directivas de Blade para facilitar la integración de las Policies y controlar la visibilidad de elementos según los permisos del usuario.
Directiva @can
La directiva @can
permite verificar si el usuario autenticado tiene permiso para realizar una acción específica.
Ejemplo de uso de @can
:
@can('update', $post)
<a href="{{ route('posts.edit', $post) }}" class="btn btn-primary">Editar</a>
@endcan
En este fragmento:
- Si el usuario tiene permiso para actualizar el post, se muestra el botón de edición.
$post
es la instancia del modelo que se pasa al método de la Policy.
Directiva @cannot
La directiva @cannot
es el inverso de @can
y se utiliza para mostrar contenido cuando el usuario no tiene permiso.
Ejemplo de uso de @cannot
:
@cannot('delete', $post)
<p>No tienes permiso para eliminar este post.</p>
@endcannot
Directiva @canany
La directiva @canany
verifica si el usuario tiene alguno de los permisos especificados.
Ejemplo de uso de @cananyç
:
@canany(['update', 'delete'], $post)
<!-- Contenido para usuarios con permiso de actualizar o eliminar -->
<div class="btn-group">
@can('update', $post)
<a href="{{ route('posts.edit', $post) }}" class="btn btn-primary">Editar</a>
@endcan
@can('delete', $post)
<form action="{{ route('posts.destroy', $post) }}" method="POST">
@csrf
@method('DELETE')
<button class="btn btn-danger">Eliminar</button>
</form>
@endcan
</div>
@endcanany
Uso de Helpers de Autorización
Además de las directivas de Blade, se pueden utilizar los helpers de autorización directamente en las vistas.
Uso del helper @auth
:
@auth
@if(Auth::user()->can('create', App\Models\Post::class))
<a href="{{ route('posts.create') }}" class="btn btn-success">Crear nuevo post</a>
@endif
@endauth
En este caso:
- Se verifica que el usuario esté autenticado con
@auth
. - Se utiliza
Auth::user()->can('create', App\Models\Post::class)
para comprobar el permiso de crear un nuevo post.
Pasando parámetros a las Policies
Para que las Policies funcionen correctamente, es esencial pasar las instancias de los modelos pertinentes tanto en los controladores como en las vistas.
En controladores:
- Al utilizar rutas con enlaces de modelos, Laravel inyecta automáticamente la instancia del modelo en los métodos del controlador.
En vistas Blade:
- Asegúrese de pasar el modelo correspondiente a las directivas
@can
y@cannot
.
Ejemplo:
@foreach($posts as $post)
<!-- Mostrar información del post -->
<h2>{{ $post->titulo }}</h2>
<p>{{ $post->contenido }}</p>
<!-- Controles basados en permisos -->
@can('update', $post)
<a href="{{ route('posts.edit', $post) }}" class="btn btn-primary">Editar</a>
@endcan
@can('delete', $post)
<form action="{{ route('posts.destroy', $post) }}" method="POST">
@csrf
@method('DELETE')
<button class="btn btn-danger">Eliminar</button>
</form>
@endcan
@endforeach
Manejo de respuestas no autorizadas
Cuando un usuario no está autorizado para realizar una acción:
- En controladores, si se utiliza
$this->authorize()
, Laravel retorna un error 403 automáticamente. - Es posible personalizar la respuesta capturando la excepción
AuthorizationException
.
Ejemplo de captura de excepción:
use Illuminate\Auth\Access\AuthorizationException;
public function update(Request $request, Post $post)
{
try {
$this->authorize('update', $post);
} catch (AuthorizationException $e) {
// Manejo personalizado de la respuesta
return redirect()->route('posts.index')->with('error', 'No tienes permiso para actualizar este post');
}
// Lógica para actualizar el post
}
Buenas prácticas al aplicar policies
- Consistencia: Utilizar un enfoque coherente para la autorización en toda la aplicación, ya sea mediante
$this->authorize()
, middlewarecan
o autorización automática. - Claridad: Especificar claramente qué acciones requieren autorización y asegurarse de que todas las rutas protegidas estén adecuadamente controladas.
- Seguridad: Nunca confíe únicamente en la lógica del frontend; siempre implemente las verificaciones de autorización en el backend.
- Eficiencia: Evite realizar llamadas innecesarias a la base de datos en las policies; obtenga toda la información necesaria de manera eficiente.
- Mantenibilidad: Agrupe la lógica de autorización relacionada en las policies para facilitar el mantenimiento y futuras modificaciones.
Recursos adicionales en Vistas
Además de las directivas mencionadas, Laravel ofrece otras herramientas para trabajar con autorización en las vistas.
Directiva @else
en @can
Se puede utilizar @else
para manejar tanto el caso autorizado como el no autorizado.
Ejemplo:
@can('view', $post)
<!-- Contenido para usuarios autorizados -->
<p>Bienvenido a la vista del post.</p>
@else
<!-- Contenido para usuarios no autorizados -->
<p>No tienes permiso para ver este post.</p>
@endcan
Directiva @forelse
con Autorización
Al iterar sobre colecciones, es posible combinar @forelse
y @can
para mostrar solo los elementos que el usuario puede ver.
Ejemplo:
@forelse($posts as $post)
@can('view', $post)
<!-- Mostrar el post -->
<h2>{{ $post->titulo }}</h2>
<p>{{ $post->contenido }}</p>
@endcan
@empty
<p>No hay posts disponibles.</p>
@endforelse
Testing de policies en controladores
Es recomendable escribir pruebas que verifiquen que las policies se aplican correctamente en los controladores.
Ejemplo de prueba unitaria:
public function test_usuario_no_autorizado_no_puede_editar_post()
{
$usuario = User::factory()->create();
$otroUsuario = User::factory()->create();
$post = Post::factory()->create(['author_id' => $otroUsuario->id]);
$this->actingAs($usuario)
->get(route('posts.edit', $post))
->assertStatus(403);
}
En esta prueba:
- Se verifica que un usuario que no es el autor del post recibe un error 403 al intentar acceder a la ruta de edición.
Casos prácticos y buenas prácticas
A continuación, exploraremos algunos casos prácticos que ilustran cómo aplicar Gates y Policies en situaciones comunes, así como buenas prácticas para optimizar la seguridad y mantenibilidad de tu aplicación Laravel.
Caso práctico 1: Control de acceso basado en roles
Una aplicación típica puede tener múltiples roles de usuario, como administrador, editor y visitante. Para gestionar los permisos de forma eficaz, es recomendable utilizar Policies y almacenar los roles en la base de datos. Por ejemplo, se puede definir un modelo de roles y establecer las relaciones correspondientes.
Definición del modelo de roles:
// Migración para la tabla de roles
Schema::create('roles', function (Blueprint $table) {
$table->id();
$table->string('nombre')->unique();
$table->timestamps();
});
// Relación en el modelo User
public function role()
{
return $this->belongsTo(Role::class);
}
Asignación de roles a usuarios:
// Asignar rol al usuario
$user->role()->associate($role);
$user->save();
Definición de una Policy basada en roles:
public function before(User $user, $ability)
{
if ($user->role->nombre === 'administrador') {
return true; // El administrador tiene acceso a todas las acciones
}
}
public function update(User $user, Post $post)
{
return $user->role->nombre === 'editor' && $user->id === $post->author_id;
}
En este ejemplo, se utiliza el método before
para otorgar a los administradores acceso total. La función update
permite a los editores actualizar solo sus propias publicaciones.
Aplicación en el controlador:
public function update(Request $request, Post $post)
{
$this->authorize('update', $post);
// Lógica para actualizar el post
}
Caso práctico 2: Permisos dinámicos y gestión de roles
Para aplicaciones que requieren una gestión de permisos más granular, es útil implementar permisos dinámicos asociados a roles. Se puede crear una estructura de tablas para roles y permisos, y definir relaciones en los modelos.
Estructura de tablas para roles y permisos:
- roles: id, nombre
- permissions: id, nombre
- permission_role: permission_id, role_id
Definición de relaciones en modelos:
// Modelo Role
public function permissions()
{
return $this->belongsToMany(Permission::class);
}
// Modelo User
public function hasPermission($permissionName)
{
return $this->role->permissions->contains('nombre', $permissionName);
}
Uso de Gates con permisos dinámicos:
Gate::define('gestionar-usuarios', function ($user) {
return $user->hasPermission('gestionar-usuarios');
});
Verificación en controladores y vistas:
// En el controlador
if (Gate::denies('gestionar-usuarios')) {
abort(403);
}
// En la vista Blade
@can('gestionar-usuarios')
<!-- Mostrar opciones de gestión de usuarios -->
@endcan
Este enfoque permite agregar o revocar permisos sin modificar el código, facilitando la flexibilidad en la administración de usuarios.
Caso práctico 3: Autorización en aplicaciones multiempresa (multi-tenant)
En aplicaciones que manejan múltiples organizaciones o clientes, es crucial asegurarse de que los usuarios solo accedan a los recursos de su propia empresa. Se pueden definir relaciones apropiadas y crear Policies que verifiquen la pertenencia a la misma empresa.
Definición de relaciones:
// Modelo Company
public function users()
{
return $this->hasMany(User::class);
}
public function posts()
{
return $this->hasMany(Post::class);
}
// Modelo User
public function company()
{
return $this->belongsTo(Company::class);
}
// Modelo Post
public function company()
{
return $this->belongsTo(Company::class);
}
Policy que verifica la pertenencia a la misma empresa:
public function view(User $user, Post $post)
{
return $user->company_id === $post->company_id;
}
Uso en el controlador:
public function show(Post $post)
{
$this->authorize('view', $post);
// Mostrar el post
}
Con esta Policy, se garantiza que un usuario solo pueda ver publicaciones relacionadas con su empresa, reforzando la seguridad de los datos.
Buenas prácticas en la gestión de autorización
Implementar las siguientes buenas prácticas ayuda a mantener un sistema de autorización efectivo y fácil de mantener.
- Centralizar la lógica de autorización: Mantén toda la lógica de permisos dentro de Policies y Gates, evitando dispersarla en controladores o modelos. Esto facilita la mantenibilidad y reduce errores.
- Utilizar Policies para modelos y Gates para acciones generales: Las Policies deben usarse para acciones que involucran a un modelo específico, mientras que las Gates son ideales para acciones globales o sin modelo asociado.
- Aplicar el principio DRY (Don't Repeat Yourself): Evita duplicar código de autorización. Si múltiples métodos requieren la misma verificación, centraliza esa lógica en una Policy o Gate.
- Aprovechar el método
before
en Policies: Utiliza el métodobefore
para manejar permisos superusuarios o reglas que se aplican antes que las demás, simplificando las demás verificaciones. - Mantener las Policies simples y claras: Cada método en una Policy debe tener una única responsabilidad y mantenerse lo más simple posible. Si la lógica es compleja, considera refactorizarla o utilizar métodos privados auxiliares.
- Proteger rutas con middleware cuando sea apropiado: Para acciones que requieren autorización constante, considera proteger las rutas con el middleware
can
, mejorando la coherencia y seguridad.
Route::post('/posts', [PostController::class, 'store'])->middleware('can:create,App\Models\Post');
- Evitar lógica de autorización en las vistas: Aunque puedes utilizar directivas como
@can
en las vistas, es mejor limitar la lógica de autorización en las vistas y manejarla en los controladores o Policies. - Documentar las Policies y Gates: Agrega comentarios y documentación a tus Policies y Gates para facilitar su comprensión, especialmente en equipos de desarrollo.
- Revisar y actualizar regularmente las Policies y Gates: Conforme tu aplicación evoluciona, es importante revisar las reglas de autorización para asegurarse de que siguen siendo relevantes y seguras.
- Escribir pruebas unitarias para la autorización: Implementa pruebas que verifiquen el comportamiento de tus Policies y Gates, garantizando que los permisos funcionan como se espera.
- Integración con pruebas unitarias
Aunque la implementación de pruebas unitarias se cubre en otra sección, es importante mencionar que validar la autorización en tus pruebas asegura que los usuarios no puedan realizar acciones no autorizadas.
Ejemplo de prueba unitaria para una Policy:
public function test_editor_puede_actualizar_su_propio_post()
{
$editor = User::factory()->create(['role' => 'editor']);
$post = Post::factory()->create(['author_id' => $editor->id]);
$this->actingAs($editor);
$this->assertTrue($editor->can('update', $post));
}
Todas las lecciones de Laravel
Accede a todas las lecciones de Laravel y aprende con ejemplos prácticos de código y ejercicios de programación con IDE web sin instalar nada.
Introducción A Php Laravel
Introducción Y Entorno
Instalación Y Configuración Laravel
Introducción Y Entorno
Controladores Mvc
Controladores Http
Vistas Y Blade Templates
Controladores Http
Formularios Y Validación
Controladores Http
Controladores Rest
Controladores Http
Middleware Y Control De Solicitudes
Persistencia
Seguridad Autenticación Y Autorización
Persistencia
Bases De Datos Y Eloquent Orm
Persistencia
Relaciones Entre Modelos
Persistencia
Consultas Avanzadas
Persistencia
Colecciones Y Métodos Avanzados
Persistencia
Migraciones Y Seeders
Persistencia
Sistema De Autenticación Nativo Laravel
Middlewares Y Seguridad
Autorización (Policies Y Gates)
Middlewares Y Seguridad
Csrf Y Protección De Formularios En Blade
Middlewares Y Seguridad
Validaciones De Datos En Controladores Y Formularios
Middlewares Y Seguridad
Cifrado De Contraseñas
Middlewares Y Seguridad
Autenticación Jwt En Api Rest
Middlewares Y Seguridad
Pruebas Unitarias Con Phpunit
Testing
Pruebas De Integración En Laravel
Testing
En esta lección
Objetivos de aprendizaje de esta lección
- Comprender el proceso de autorización en Laravel para controlar el acceso a recursos.\n- Aprender a definir y utilizar Gates para acciones específicas.\n- Encontrar el uso de Policies en la gestión de permisos basada en modelos.\n- Implementar verificación de roles y permisos con ejemplos prácticos.\n- Aplicar buenas prácticas para estructurar reglas de autorización.