Una lista de control de acceso es una lista adjunta a un recurso que nombra qué usuarios o roles pueden acceder a él y qué puede hacer cada uno. La adjunción es la idea: donde los sistemas de roles cuelgan los permisos de las personas, una ACL los cuelga del objeto — cada registro con su propia lista de invitados, cada entrada (una entrada de control de acceso, ACE) un sujeto emparejado con sus derechos. Es una de las construcciones de seguridad más antiguas de la computación, y en los backends de aplicación es cómo “solo Ada y los editores pueden tocar este documento” se convierte en un campo en lugar de una feature.
Puntos clave
| Pregunta | Respuesta |
|---|---|
| La estructura | Objeto → lista de entradas · cada entrada = sujeto + permisos |
| Los tres significados | Filtros de tráfico de red · permisos de archivos · ACLs por registro en la aplicación |
| vs. RBAC | La ACL responde “¿quién puede tocar este objeto?” — RBAC, “¿qué puede hacer este rol?” |
| La salida a escala | Entradas de rol + ACLs por defecto + reglas a nivel de clase para el caso común |
| La ley de hierro | Evaluada del lado del servidor, en cada solicitud — nunca en el cliente |
La lista de invitados de un objeto
Documento "Roadmap Q3" — ACL
┌────────────────────┬─────────┬───────────┐
│ sujeto │ lectura │ escritura │
├────────────────────┼─────────┼───────────┤
│ user usr-8fk2 (Ada)│ sí │ sí │ ← propietaria
│ user usr-2mq7 (Bob)│ sí │ — │ ← grant individual
│ role editors │ sí │ sí │ ← un rol como una entrada
│ público (todos) │ — │ — │ ← por defecto: cerrado
└────────────────────┴─────────┴───────────┘
Como dato, en el propio registro:
{ "title": "Q3 roadmap",
"ACL": { "usr-8fk2": { "read": true, "write": true },
"usr-2mq7": { "read": true },
"role:editors": { "read": true, "write": true } } }
Escribir esa lista de invitados en código de aplicación:
// JavaScript / Node.js — Back4app JS SDK
// A per-object ACL: this document's own guest list
const doc = new Parse.Object('Document');
doc.set('title', 'Q3 roadmap');
const acl = new Parse.ACL(currentUser); // owner: read + write
acl.setReadAccess(reviewerId, true); // one user: read only
acl.setRoleWriteAccess('editors', true); // a role as an entry
acl.setPublicReadAccess(false); // everyone else: nothing
doc.setACL(acl);
await doc.save(); // enforced server-side on every future request // Flutter / Dart — Back4app Flutter SDK
// A per-object ACL: this document's own guest list
final doc = ParseObject('Document')..set('title', 'Q3 roadmap');
final acl = ParseACL(owner: currentUser); // owner: read + write
acl.setReadAccess(userId: reviewerId, allowed: true); // one user: read only
acl.setRoleWriteAccess('editors', true); // a role as an entry
acl.setPublicReadAccess(allowed: false); // everyone else: nothing
doc.setACL(acl);
await doc.save(); // enforced server-side on every future request // iOS / Swift — Back4app Swift SDK
// A per-object ACL: this document's own guest list
var doc = Document()
doc.title = "Q3 roadmap"
var acl = ParseACL()
acl.setReadAccess(user: currentUser, value: true) // owner: read…
acl.setWriteAccess(user: currentUser, value: true) // …and write
acl.setReadAccess(objectId: reviewerId, value: true) // one user: read only
acl.setWriteAccess(roleName: "editors", value: true) // a role as an entry
acl.publicRead = false // everyone else: nothing
doc.ACL = acl
try await doc.save() // enforced server-side on every future request // Android / Kotlin — Back4app Android SDK
// A per-object ACL: this document's own guest list
val doc = ParseObject("Document")
doc.put("title", "Q3 roadmap")
val acl = ParseACL(ParseUser.getCurrentUser()) // owner: read + write
acl.setReadAccess(reviewerId, true) // one user: read only
acl.setRoleWriteAccess("editors", true) // a role as an entry
acl.publicReadAccess = false // everyone else: nothing
doc.acl = acl
doc.save() // enforced server-side on every future request Los tres significados de “ACL”
La mayoría de las explicaciones elige uno en silencio; el término nombra, de hecho, tres mecanismos:
| Familia | Adjunta a | Una entrada se ve como | Evaluada por |
|---|---|---|---|
| ACLs de red | Interfaces de router/firewall | Regla allow/deny sobre IPs, puertos, protocolo — ordenada, gana la primera coincidencia, deny implícito al final | Dispositivos de red |
| ACLs de sistema de archivos | Archivos y directorios | user:ada:rw- — extendiendo propietario/grupo/otros (POSIX acl(5)) | El sistema operativo |
| ACLs de aplicación | Filas, documentos, objetos | Usuario/rol → flags de lectura/escritura en el registro | Tu backend, por solicitud |
Comparten la forma — una lista de entradas sujeto-permiso custodiando un recurso — y difieren en todo lo demás. La casa de este artículo es el tercer significado: las listas de permisos por registro de los backends de aplicación, el menos cubierto y, para quien desarrolla producto, el más usado.
Cómo se evalúa una solicitud: el modelo de dos gates
Las capas son la manera en que los sistemas maduros concilian el control grueso y el fino: los permisos a nivel de clase declaran la política de la categoría entera (“solo usuarios autenticados; solo los moderadores eliminan”), y la ACL por objeto decide el registro individual. Una solicitud debe pasar ambos gates — lo que significa que una ACL olvidada no puede abrir lo que la regla de la clase cerró, y una regla de clase generosa tampoco puede exponer un objeto bloqueado. La misma lógica de capas aparece un nivel más abajo como seguridad a nivel de fila, cuando la propia base de datos aplica el predicado por fila.
ACL vs. RBAC vs. ABAC
| ACL | RBAC | ABAC | |
|---|---|---|---|
| Los permisos se adjuntan a | Cada objeto | Roles asignados a usuarios | Reglas sobre atributos |
| Pregunta nativa | ¿Quién puede tocar este objeto? | ¿Qué puede hacer este rol? | ¿Se permite este acceso en contexto? |
| Granularidad | La más fina — por registro, por usuario | Gruesa — por función | Arbitraria — por condición |
| Costo de administración | Crece con objetos × sujetos | Crece con los roles | Crece con la complejidad de las reglas |
| Auditar “¿quién ve X?” | Trivial — lee la lista de X | Indirecto — expande los roles | Difícil — evalúa las reglas |
| Auditar “¿qué puede ver Ada?” | Difícil — recorre todos los objetos | Trivial — lee sus roles | Difícil |
| Debilidad | Proliferación de listas | Explosión de roles, sin matiz por objeto | Depuración opaca de políticas |
La respuesta honesta es composición, no competencia: los roles manejan el acceso que sigue la función de trabajo; las ACLs manejan las decisiones por objeto que los roles no pueden expresar (“este borrador, estos dos revisores”); las reglas de atributos entran cuando el contexto importa (hora, tenant, estado). La bisagra práctica entre los dos primeros es la ACE de rol — una línea de la ACL cuyo sujeto es un rol — que conserva el control a nivel de objeto mientras delega la rotación de miembros al sistema de roles.
El problema de escala — y la escalera de mitigación
Las ACLs por objeto ingenuas crecen como N objetos × M sujetos: un millón de documentos, cada uno listando usuarios individuales, significa que cada contratación, salida y reorganización edita listas dispersas por todo el dataset — el “difícil de gestionar” que menciona todo libro de texto, hecho concreto. La escalera de mitigación, en el orden en que se sube: entradas de rol (una ACE cubre una población que cambia; la membresía se actualiza en un solo lugar); ACLs por defecto (cada objeto nuevo nace con lectura/escritura del propietario y las entradas de rol correctas — el análogo en la aplicación de las ACLs default de POSIX en directorios); reglas a nivel de clase para el caso común, reservando las listas por objeto para las excepciones; y, a escala pesada de relaciones, autorización basada en grafos (ReBAC), que deriva el acceso de las relaciones en lugar de almacenar listas. Los sistemas que se saltan la escalera no abandonan las ACLs — se ahogan en ellas.
Enforcement: del lado del servidor o nada
Una ACL aplicada en el cliente es una sugerencia. Ocultar botones, filtrar listas en JavaScript o confiar en que la app solo envíe IDs permitidos fallan de la misma manera: el atacante edita la solicitud, no la interfaz — incrementa /documents/41 a /documents/42 y lee el registro de otra persona. Esa clase de falla — broken object-level authorization, el primer puesto de la lista de seguridad de APIs de OWASP — es exactamente lo que las ACLs por objeto existen para cerrar, y la guía de OWASP es directa: las verificaciones de autorización corren del lado del servidor, por solicitud, por objeto; tener acceso a un tipo de objeto nunca implica acceso a todo objeto de ese tipo. La evaluación pertenece a la capa de datos, donde ningún camino del cliente puede rodearla.
Casos de uso comunes
- Contenido generado por usuarios — cada post, archivo o nota pertenece a quien lo creó, compartido registro a registro.
- Colaboración en documentos — listas de lectores/editores por documento; el diálogo de compartir es un editor de ACL vestido de UX.
- Registros multiusuario con excepciones — el caso de RR. HH.: el titular del registro lo lee, su gerente lo escribe, el rol de auditores lo lee todo.
- Alcance por tenant y por equipo — entradas de rol por equipo en clases compartidas, con grants por objeto para las excepciones entre equipos.
- Apps privadas por defecto — mensajería, salud, finanzas: cada objeto cerrado al crearse, abierto solo por entradas explícitas.
¿Deberías usar ACLs o roles? Matriz de decisión
| Situación | Elige |
|---|---|
| El acceso sigue la función de trabajo a través de muchos registros | Roles (RBAC) |
| Cada registro necesita sus propias decisiones de compartición | ACLs |
| Ambos patrones a la vez (la mayoría de las apps reales) | Reglas de clase + ACLs con entradas de rol |
| ”Todos leen, el propietario escribe” | Flag de lectura pública en la ACL + entrada del propietario |
| Las reglas dependen del contexto (hora, estado, tenant) | Condiciones de atributos por encima de la ACL |
| Lógica profunda de relaciones (organigramas, grupos anidados) | Sistemas estilo ReBAC |
Limitaciones y trade-offs
- La proliferación es la trayectoria por defecto. Sin entradas de rol y valores por defecto, las listas por objeto se vuelven confeti inauditable; la escalera de mitigación no es opcional a escala.
- “¿A qué puede acceder este usuario?” es la consulta cara. Las ACLs optimizan la auditoría por objeto; el inventario por sujeto exige recorridos o índices secundarios.
- Los defaults equivocados son brechas silenciosas. Un objeto creado con lectura pública sigue público hasta que alguien lo nota; las ACLs por defecto merecen la misma revisión que el código.
- El rendimiento carga con la verificación. Cada lectura filtra por ACL; la evaluación debe estar indexada y aplicarse en la capa de datos, no parcharse endpoint por endpoint.
- Las ACLs autorizan; no autentican. La lista vale lo que vale la identidad que se le presenta — las sesiones y los tokens son la dependencia aguas arriba.
ACLs en Back4app
Back4app es una plataforma open-source de Backend as a Service (BaaS) que combina base de datos gestionada, APIs REST y GraphQL generadas automáticamente, autenticación, almacenamiento de archivos y funciones serverless con Cloud Code. Aquí la ACL es un campo de primera clase: cada objeto lleva una, las pestañas de código de arriba son la API completa — valores por defecto del propietario, grants por usuario, entradas de rol, flags públicas — y el enforcement ocurre en Back4app en cada solicitud REST, GraphQL y Live Query, así que las suscripciones en tiempo real respetan las mismas listas de invitados que las consultas. El modelo de dos gates llega intacto: los permisos a nivel de clase fijan la política de la categoría en el dashboard, las ACLs por objeto la refinan registro a registro, y una configuración de ACL por defecto hace que los objetos nuevos nazcan privados de su propietario. La escalera de escala viene montada — los roles son objetos que gestionas como cualquier otro dato — dejando las decisiones de diseño, y no la maquinaria de enforcement, como tu parte del trabajo.
Preguntas frecuentes
¿Qué es una ACL en términos simples?
Una lista de invitados adjunta a cada recurso: nombra quién puede acceder a ese objeto específico y qué puede hacer cada uno — Ada lee y escribe, Bob solo lee, todos los demás quedan fuera. La lista viaja con el objeto, así que cada objeto puede tener reglas distintas.
¿Qué es una entrada de control de acceso (ACE)?
Una línea de la lista: un sujeto (un usuario, un rol o "todos") emparejado con los permisos que se le conceden o deniegan. Una ACL es simplemente una colección ordenada de ACEs adjunta a un único recurso.
¿Cuáles son los tipos de ACL?
Tres familias comparten el nombre: las ACLs de red (filtros de tráfico ordenados en routers y firewalls), las ACLs de sistema de archivos (listas de permisos por archivo que extienden propietario/grupo/otros) y las ACLs de aplicación o de base de datos (listas de permisos por registro en tu capa de datos). En desarrollo backend, la tercera es normalmente la que se quiere decir.
¿Cuál es la diferencia entre ACL y RBAC?
La dirección del vínculo. Una ACL cuelga los permisos de cada recurso, por sujeto — ideal cuando objetos individuales exigen decisiones individuales. RBAC cuelga los permisos de roles y asigna usuarios a ellos — ideal cuando el acceso sigue la función de trabajo a través de muchos recursos. Los sistemas reales combinan ambos: roles para el grueso, ACLs para las excepciones por objeto.
¿Cómo funcionan las ACLs en una base de datos?
Cada fila o documento lleva (o referencia) su propia lista de permisos — típicamente un campo ACL que mapea IDs de usuario y nombres de rol a flags de lectura/escritura. La base de datos o el backend la evalúa en cada operación, lo que combina de forma natural con la seguridad a nivel de fila y las capas de permisos por tabla.
¿Cuál es la diferencia entre una ACL y una capability list?
Dos vistas de la misma matriz de acceso: la ACL es una columna — almacenada con el objeto, listando sus sujetos — y la capability list es una fila — almacenada con el sujeto, listando sus objetos. Las ACLs hacen que "¿quién puede tocar este objeto?" sea auditable al instante; las capabilities facilitan "¿qué puede tocar este usuario?", pero complican la revocación.
¿Por qué las ACLs no escalan por sí solas?
Porque la contabilidad crece como objetos × sujetos: cada contratación, salida y cambio de equipo significa editar listas dispersas por millones de objetos. Las mitigaciones son las entradas de rol (una ACE cubre un grupo que cambia), las ACLs por defecto aplicadas en la creación y las reglas a nivel de clase que manejan el caso común, dejando las listas por objeto solo para las excepciones.
¿Cuál es la diferencia entre permisos por objeto y por clase?
Granularidad. Los permisos por clase (o por tabla) controlan una categoría entera — "solo los usuarios con sesión pueden consultar Documents". Las ACLs por objeto controlan un registro — "solo Ada puede leer este documento". Los sistemas en capas verifican primero el gate de la clase y después la ACL del objeto; la solicitud debe pasar ambos.