Ir al contenido principal

Es mala práctica incluir el usuario logueado en todas las URLs autenticadas

 Quiero que todas las URLs que están autenticadas tengan como parte del path al usuario logueado en la forma de "/user/123" (donde "123" es el id del usuario logueado). Quiero que inmediatamente después de estar autenticado un usuario, todas las URLs tengan esa forma. ¿Te parece una buena práctica? ¿Cómo se hace?

No, en general, no es una buena práctica que todas las URLs autenticadas incluyan el ID del usuario en el path de forma obligatoria.

Si bien podría parecer una forma directa de segmentar el contenido, esta estrategia introduce varias desventajas significativas que afectan el rendimiento, la escalabilidad y la arquitectura de tu aplicación.


Por qué no es una buena práctica

  • Impacto en el Caching: Las URLs que incluyen el ID del usuario no se pueden almacenar en caché a nivel de servidor o CDN. Cada usuario tiene una URL única (/user/123/dashboard vs. /user/456/dashboard), lo que significa que el servidor no puede servir una versión común de la página. Esto aumenta la carga del servidor y la latencia para cada solicitud, ya que cada una debe ser procesada individualmente.

  • Violación del Diseño RESTful: En un diseño RESTful, una URL debe identificar un recurso, no el usuario que lo solicita. El servidor ya sabe quién eres a través de la sesión o el token de autenticación. Incluir el ID en la URL es redundante y crea URLs artificiales que no representan el recurso subyacente de manera limpia.

  • Complejidad de Mantenimiento: Cada vez que generes una URL (link o form action), tendrás que recordar agregar el ID del usuario. Esto hace que tu código sea más propenso a errores y más difícil de mantener a medida que la aplicación crece.

  • Redireccionamiento Extra: Forzar un redirect después del login para agregar el ID del usuario añade una solicitud HTTP extra, lo que aumenta la latencia antes de que el usuario vea la primera página.

La forma estándar y recomendada de manejar este tipo de lógica es permitir que el servidor obtenga el ID del usuario desde la sesión (auth()->id()) o un token, y luego usar ese ID para recuperar los datos correctos del usuario, sin necesidad de que el ID esté en la URL.


Cómo se hace (con sus riesgos)

A pesar de las desventajas, si decides proceder con esta estrategia, la forma más limpia de implementarla en Laravel es mediante el redirect después del login y el uso de un prefijo de ruta.

1. Configurar la redirección después del login

Por defecto, Laravel redirige a /home o a la URL que le especifiques en la propiedad redirectTo. Puedes anular esto con el método redirectTo() para crear la URL personalizada.

Controlador de Login
<?php

namespace App\Http\Controllers\Auth;

use App\Http\Controllers\Controller;
use Illuminate\Foundation\Auth\AuthenticatesUsers;

class LoginController extends Controller
{
use AuthenticatesUsers;

/**
* Where to redirect users after login.
*
* @var string
*/
protected function redirectTo()
{
return '/user/' . auth()->user()->id . '/dashboard';
}

/**
* Create a new controller instance.
*
* @return void
*/
public function __construct()
{
$this->middleware('guest')->except('logout');
}
}

auth()->user()->id obtendrá el ID del usuario autenticado y construirá la URL de forma dinámica.

2. Definir las rutas con un prefijo

Todas las rutas que necesiten el ID del usuario deben estar dentro de un grupo de rutas con un prefijo dinámico.

Con esta configuración, la URL se construye como tú la necesitas. Sin embargo, en tu controlador, tendrás que recordar que el ID del usuario también se te pasa como un parámetro de la ruta ({user} en este caso) que, aunque Laravel lo tenga disponible en auth()->user(), también puede ser accedido a través de la firma del método de la siguiente manera:

Ejemplo de Controlador
<?php

namespace App\Http\Controllers;

use Illuminate\Http\Request;

class DashboardController extends Controller
{
/**
* Show the user's dashboard.
*
* @param \Illuminate\Http\Request $request
* @param string $user
* @return \Illuminate\Http\Response
*/
public function index(Request $request, string $user)
{
// En este punto, $user contendrá el ID de la URL
// Por seguridad, siempre debes usar el ID del usuario autenticado
// para buscar los datos.
$loggedInUserId = $request->user()->id;

if ($user != $loggedInUserId) {
// El usuario de la URL no coincide con el autenticado.
// Manejar como un error 403 o una redirección.
abort(403);
}

// ... Lógica para mostrar el dashboard del usuario.
}
}

En resumen, si bien es posible implementarlo, te recomiendo fuertemente que optes por la convención estándar de Laravel: usar el ID del usuario autenticado a través de la sesión, sin incluirlo en las URLs.

Comentarios

Entradas populares de este blog

Crear proyecto de frontend con Vite, React, Tailwind, Typescript y JSX

 ¿Cómo se crea un proyecto exclusivo de frontend con Vite, React, Tailwind, Typescript y JSX? ¡Absolutamente! Entiendo que quieres la guía completa para pasar de cero a tener un proyecto de frontend moderno, vacío y listo para ser llenado con tu código. A continuación, te proporciono un archivo de guía detallada que incluye todos los comandos necesarios para inicializar el proyecto, configurar Tailwind CSS, y los pasos clave para empezar a "poblarlo". Voy a generar un documento Markdown con la guía paso a paso, incluyendo los comandos de terminal y las modificaciones esenciales a los archivos de configuración. Guía: Creación de un Proyecto Frontend Puro (Vite, React, TypeScript, Tailwind) Este documento detalla el proceso para inicializar un proyecto de frontend vacío y optimizado, utilizando Vite como empaquetador, React como librería, TypeScript para tipado y Tailwind CSS para estilizado. 1. Inicialización del Proyecto con Vite Vite es la herramienta más rápida para emp...

Tokens V2

Tokens: Programme to discover tokens, where there are not. Now available at  https://puszcza.gnu.org.ua/projects/tokens/ This is Version 2, for  version 1, go here . Synopsis: use TokensV2; sub printFile; my @FORMAT = ( ['<Message Date=".*?" Time=".*?" DateTime=".*?" SessionID=".*?"><From>(?:<User FriendlyName=".*?"/>)+</From><To>(?:<User FriendlyName=".*?"/>)+</To><Text(?: Style=".*?")?>.*?</Text></Message>',   sub {     my $fh = $_[1];     my ($d, $t, $f, $s, $T) = $_[0] =~ m|<Message Date="(.*?)" Time="(.*?)" DateTime=".*?" SessionID=".*?">(<From>(?:<User FriendlyName=".*?"/>)+</From>)<To>(?:<User FriendlyName=".*?"/>)+</To><Text(?: Style="(.*?)")?>(.*?)</Text></Message>|;     my $F = join '<br />', ...

Perl Net::LDAP::SimpleServer

Adaptaciones sobre el módulo LDAP Server para Windows (Strawberry Perl) Lista de adaptaciones (continúa más abajo): - Relajación de condiciones de bind:     - Cuenta principal (principal account)     - Validación de contraseñas Ubicación del archivo: %Strawberry_Perl%\site\lib\net\ldap\SimpleServer\ProtocolHandler.pm CPAN: http://search.cpan.org/~russoz/Net-LDAP-SimpleServer-0.0.17/lib/Net/LDAP/SimpleServer.pm Código: package Net::LDAP::SimpleServer::ProtocolHandler; use strict; use warnings; # ABSTRACT: LDAP protocol handler used with Net::LDAP::SimpleServer our $VERSION = '0.0.17';    # VERSION use Net::LDAP::Server; use base 'Net::LDAP::Server'; use fields qw(store root_dn root_pw allow_anon); use Carp; use Net::LDAP::LDIF; use Net::LDAP::Util qw{canonical_dn}; use Net::LDAP::FilterMatch; use Net::LDAP::Constant (     qw/LDAP_SUCCESS LDAP_AUTH_UNKNOWN LDAP_INVALID_CREDENTIALS/,   ...