¿QUÉ ES ACL EN LA GESTIÓN DE USUARIOS EN UNA APLICACIÓN WEB?

ACL, Access Control Listo Lista de Control de Acceso, es una forma de control de permisos. En lugar de solo tener roles como Admin, Editor, Usuario, etc., ACL permite controlar accesos a nivel muy específico.

ACL Es un mecanismo de seguridad que permite definir qué usuarios o roles pueden realizar qué acciones sobre los recursos de tu aplicación.
Usuario / Rol Ver proyectos Crear proyecto Editar proyecto Eliminar proyecto Ver reportes financieros
ADMINISTRADOR SI SI SI SI SI
EDITOR SI SI SI NO NO
USUARIO NORMAL SI NO Solo los suyos NO NO
INVITADO Solo públicos NO NO NO NO

Componentes del ACL

  • Recursos (Resources): Lo que se quiere proteger (proyectos, usuarios, archivos, facturas, etc.)
  • Acciones (Permissions): Qué se puede hacer (leer, crear, actualizar, borrar, aprobar, etc.)
  • Sujetos (Subjects): Quién quiere hacer la acción (usuario específico, rol, grupo)
  • Reglas: Combinación de los tres anteriores.

Tipos de ACL más usados

Tipo Descripción Cuándo usarlo
Role-Based (RBAC) Permisos basados en roles La mayoría de aplicaciones
ACL Clásico Lista directa de permisos por usuario/recurso Cuando necesitas granularidad
ABAC Attribute Based Access Control (más avanzado) Aplicaciones complejas
PBAC Policy Based Access Control Empresas grandes

Ventajas de usar ACL

  • Mayor seguridad y control.
  • Permisos muy granulares.
  • Fácil auditoría de quién puede hacer qué.
  • Flexible para crecer.

Desventajas de usar ACL

  • Puede volverse complejo si no se diseña bien.
  • Más trabajo de mantenimiento.

Alternativas

  • Casbin (muy popular)
  • AccessControl (librería JS)
  • Permify
  • Keycloak + RBAC
  • Firebase Security Rules / Supabase RLS

Ejemplo de ACL con php

class ACL {
    
    private $permissions = [];

   public function __construct() {
   // Definición de permisos por rol
   $this->permissions = [
  'admin' => [
      'ver_proyectos'     => true,
      'crear_proyecto'    => true,
      'editar_proyecto'   => true,
      'eliminar_proyecto' => true,
      'ver_reportes' => true,
  ],
  'editor' => [
      'ver_proyectos'     => true,
      'crear_proyecto'    => true,
      'editar_proyecto'   => true,
      'eliminar_proyecto' => false,
      'ver_reportes' => false,
  ],
  'usuario' => [
      'ver_proyectos'     => true,
      'crear_proyecto'    => false,
      'editar_proyecto'   => 'own',     // Solo puede editar sus propios proyectos
      'eliminar_proyecto' => false,
      'ver_reportes' => false,
  ],
  'invitado' => [
      'ver_proyectos'     => 'public',  // Solo puede ver proyectos públicos
      'crear_proyecto'    => false,
      'editar_proyecto'   => false,
      'eliminar_proyecto' => false,
      'ver_reportes' => false,
  ]
   ];
    }
 /**
     * Verifica si un rol tiene permiso para realizar una acción
     * 
     * @param string $role   Rol del usuario (admin, editor, usuario, etc.)
     * @param string $action      Acción a verificar (ver_proyectos, crear_proyecto, etc.)
     * @param int|null $resourceOwnerId  ID del dueño del recurso (para permisos 'own')
     * @param int|null $userId    ID del usuario actual
     * @return bool
     */
    public function tienePermiso($role, $action, $resourceOwnerId = null, $userId = null) {
   
   // Si el rol no existe, denegar acceso por seguridad
   if (!isset($this->permissions[$role])) {
  return false;
   }

   $permission = $this->permissions[$role][$action] ?? false;

   // Caso especial: Solo puede editar/ver sus propios recursos
   if ($permission === 'own') {
  return $resourceOwnerId == $userId;
   }

   // Caso especial: Solo puede ver recursos públicos
   if ($permission === 'public') {
  return true; // Aquí iría la lógica real según tu aplicación
   }

   // Permiso normal (true o false)
   return (bool) $permission;
    }
}

// ==================== EJEMPLO DE USO ====================

$acl = new ACL();

echo "Pruebas de Permisos";
$userId = 15; // ID del usuario actual
// Ejemplos más legibles
$userId = 15; // ID del usuario actual

echo "Admin puede crear proyecto? → " . 
     ($acl->tienePermiso('admin', 'crear_proyecto') ? 'SI' : 'NO') . "

"; echo "Usuario puede editar su propio proyecto? → " . ($acl->tienePermiso('usuario', 'editar_proyecto', $userId, $userId) ? 'SI' : 'NO'); echo "Usuario puede editar proyecto de otro? → " . ($acl->tienePermiso('usuario', 'editar_proyecto', 25, $userId) ? 'SI' : 'NO'); echo "Editor puede eliminar proyecto? → " . ($acl->tienePermiso('editor', 'eliminar_proyecto') ? 'SI' : 'NO'); echo "Invitado puede ver proyectos? → " . ($acl->tienePermiso('invitado', 'ver_proyectos') ? 'SI (públicos)' : 'NO');