Una lista di controllo degli accessi è una lista allegata a una risorsa che indica quali utenti o ruoli possono accedervi e che cosa ciascuno può fare. Tutto sta nell’aggancio: dove i sistemi a ruoli appendono i permessi alle persone, un’ACL li appende all’oggetto – ogni record con la propria lista degli invitati, ogni voce (una voce di controllo degli accessi, o ACE) un soggetto abbinato ai suoi diritti. È una delle costruzioni di sicurezza più antiche dell’informatica e, nei backend applicativi, è ciò che trasforma “solo Ada e gli editor possono toccare questo documento” in un campo invece che in una feature.
Punti chiave
| Domanda | Risposta |
|---|---|
| La struttura | Oggetto → elenco di voci · ogni voce = soggetto + permessi |
| I tre significati | Filtri del traffico di rete · permessi dei file · ACL applicative per record |
| vs. RBAC | L’ACL risponde a “chi può toccare questo oggetto?” – RBAC a “che cosa può fare questo ruolo?” |
| La soluzione per la scalabilità | Voci di ruolo + ACL predefinite + regole di classe per il caso comune |
| La regola d’oro | Valutata lato server, a ogni richiesta – mai nel client |
La lista degli invitati di un oggetto
Documento "Q3 roadmap" — ACL
┌─────────────────────┬─────────┬───────────┐
│ soggetto │ lettura │ scrittura │
├─────────────────────┼─────────┼───────────┤
│ user usr-8fk2 (Ada) │ sì │ sì │ ← proprietario
│ user usr-2mq7 (Bob) │ sì │ — │ ← concesso singolarmente
│ role editors │ sì │ sì │ ← un ruolo, una sola voce
│ public (tutti) │ — │ — │ ← predefinito: chiuso
└─────────────────────┴─────────┴───────────┘
Sotto forma di dati, sul record stesso:
{ "title": "Q3 roadmap",
"ACL": { "usr-8fk2": { "read": true, "write": true },
"usr-2mq7": { "read": true },
"role:editors": { "read": true, "write": true } } }
Scrivere quella lista degli invitati nel codice applicativo:
// 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 I tre significati di “ACL”
Quasi tutte le spiegazioni ne scelgono uno senza dirlo; il termine designa davvero tre meccanismi:
| Famiglia | Allegata a | Una voce ha questa forma | Valutata da |
|---|---|---|---|
| ACL di rete | Interfacce di router/firewall | Regola allow/deny su IP, porte, protocollo – ordinata, vince la prima corrispondenza, deny implicito in coda | I dispositivi di rete |
| ACL dei file system | File e directory | user:ada:rw- – estensione di proprietario/gruppo/altri (POSIX acl(5)) | Il sistema operativo |
| ACL applicative | Righe, documenti, oggetti | Utente/ruolo → flag di lettura/scrittura sul record | Il backend, a ogni richiesta |
Condividono la forma – un elenco di voci soggetto-permesso che presidia una risorsa – e divergono su tutto il resto. Questo articolo tratta il terzo significato: le liste di permessi per record dei backend applicativi, il meno documentato e, per chi sviluppa prodotti, il più usato.
Come viene valutata una richiesta: il modello a due barriere
Gli strati sono il modo in cui i sistemi maturi conciliano controllo grossolano e controllo fine: i permessi di classe enunciano la politica dell’intera categoria (“solo utenti autenticati; solo i moderatori eliminano”) e l’ACL per oggetto decide sul singolo record. Una richiesta deve superare entrambe le barriere – il che significa che un’ACL dimenticata non può aprire ciò che la regola di classe ha chiuso, e una regola di classe generosa non può comunque esporre un oggetto bloccato. La stessa logica a strati ricompare un livello più in basso come sicurezza a livello di riga, quando è il database stesso ad applicare il predicato sulla riga.
ACL vs. RBAC vs. ABAC
| ACL | RBAC | ABAC | |
|---|---|---|---|
| I permessi si agganciano a | Ogni oggetto | Ruoli assegnati agli utenti | Regole su attributi |
| Domanda nativa | Chi può toccare questo oggetto? | Che cosa può fare questo ruolo? | L’accesso è lecito in questo contesto? |
| Granularità | La più fine – per record, per utente | Grossolana – per funzione | Arbitraria – per condizione |
| Costo di amministrazione | Cresce come oggetti × soggetti | Cresce con i ruoli | Cresce con la complessità delle regole |
| Verificare “chi vede X?” | Banale – leggere la lista di X | Indiretto – espandere i ruoli | Difficile – valutare le regole |
| Verificare “che cosa vede Ada?” | Difficile – scorrere tutti gli oggetti | Banale – leggere i suoi ruoli | Difficile |
| Punto debole | Proliferazione delle liste | Esplosione dei ruoli, nessuna sfumatura per oggetto | Politiche opache da debuggare |
La risposta onesta è la composizione, non la concorrenza: i ruoli gestiscono l’accesso che segue la funzione lavorativa; le ACL gestiscono le decisioni su singoli oggetti che i ruoli non sanno esprimere (“questa bozza, questi due revisori”); le regole per attributi subentrano quando conta il contesto (orario, tenant, stato). La cerniera pratica fra i primi due è l’ACE di ruolo – una riga di ACL il cui soggetto è un ruolo – che conserva il controllo a livello di oggetto delegando al sistema dei ruoli il ricambio dei membri.
Il problema della scalabilità – e la scala delle mitigazioni
Le ACL per oggetto scritte in modo ingenuo crescono come N oggetti × M soggetti: un milione di documenti che elencano ciascuno utenti singoli significa che ogni assunzione, uscita e riorganizzazione modifica liste sparse per tutto l’insieme dei dati – il “difficile da gestire” che citano tutti i manuali, reso concreto. I pioli della scala delle mitigazioni, nell’ordine in cui conviene salirli: le voci di ruolo (una sola ACE copre una popolazione che cambia; l’appartenenza si aggiorna in un unico posto); le ACL predefinite (ogni nuovo oggetto nasce con lettura/scrittura per il proprietario e con le voci di ruolo giuste – l’equivalente applicativo delle ACL predefinite POSIX sulle directory); le regole di classe per il caso comune, riservando le liste per oggetto alle eccezioni; e, su scale ricche di relazioni, l’autorizzazione basata su grafo (ReBAC), che deduce l’accesso dalle relazioni invece di memorizzare liste. I sistemi che saltano i pioli non abbandonano le ACL – ci affogano.
Applicazione delle regole: lato server o per niente
Un’ACL applicata nel client è un suggerimento. Nascondere pulsanti, filtrare elenchi in JavaScript o confidare che l’app invii solo gli ID consentiti falliscono tutti nello stesso modo: chi attacca modifica la richiesta, non l’interfaccia – trasforma /documents/41 in /documents/42 e legge il record di qualcun altro. Quella classe di falle – broken object-level authorization, la prima voce dell’elenco OWASP sulla sicurezza delle API – è precisamente ciò che le ACL per oggetto esistono per chiudere, e la guida OWASP è netta: i controlli di autorizzazione girano lato server, a ogni richiesta, per ogni oggetto; avere accesso a un tipo di oggetto non implica mai l’accesso a tutti gli oggetti di quel tipo. La valutazione va collocata nello strato dei dati, dove nessun percorso del client può aggirarla.
Casi d’uso tipici
- Contenuti generati dagli utenti – ogni post, file o nota appartiene a chi l’ha creato e si condivide record per record.
- Collaborazione sui documenti – liste di lettori/editor per documento; la finestra di condivisione è un editor di ACL vestito da UX.
- Record multiutente con eccezioni – il caso HR: la persona interessata legge la propria scheda, il suo manager la modifica, il ruolo dei revisori legge tutto.
- Confinamento per tenant e per squadra – voci di ruolo per squadra sulle classi condivise, con concessioni per oggetto per le eccezioni fra squadre.
- App private per impostazione predefinita – messaggistica, salute, finanza: ogni oggetto chiuso alla creazione, aperto solo da voci esplicite.
Conviene usare le ACL o i ruoli? Matrice decisionale
| Situazione | Scegliere |
|---|---|
| L’accesso segue la funzione lavorativa su molti record | I ruoli (RBAC) |
| Ogni record ha bisogno di decisioni di condivisione proprie | Le ACL |
| Entrambi gli schemi insieme (quasi tutte le app reali) | Regole di classe + ACL con voci di ruolo |
| ”Tutti leggono, il proprietario scrive” | Flag di lettura pubblica nell’ACL + voce del proprietario |
| Le regole dipendono dal contesto (orario, stato, tenant) | Condizioni su attributi sopra l’ACL |
| Logica relazionale profonda (organigrammi, gruppi annidati) | Sistemi di tipo ReBAC |
Limiti e trade-off
- La proliferazione è la traiettoria predefinita. Senza voci di ruolo e senza valori predefiniti, le liste per oggetto diventano coriandoli impossibili da verificare; a grande scala i pioli delle mitigazioni non sono opzionali.
- “A che cosa ha accesso questo utente?” è la query costosa. Le ACL ottimizzano la verifica per oggetto; l’inventario per soggetto richiede una scansione o indici secondari.
- Valori predefiniti sbagliati sono violazioni silenziose. Un oggetto creato leggibile pubblicamente resta pubblico finché qualcuno non se ne accorge; le ACL predefinite meritano la stessa revisione del codice.
- Le prestazioni dipendono dal controllo. Ogni lettura filtra in base all’ACL; la valutazione va indicizzata e applicata nello strato dei dati, non innestata endpoint per endpoint.
- Le ACL autorizzano; non autenticano. La lista vale quanto l’identità che le viene presentata – sessioni e token sono la dipendenza a monte.
Le ACL su Back4app
Back4app è una piattaforma open-source di Backend as a Service (BaaS) che combina database gestito, API REST e GraphQL generate automaticamente, autenticazione, archiviazione di file e funzioni serverless con Cloud Code. Qui l’ACL è un campo di primo piano: ogni oggetto ne porta una, le schede di codice qui sopra sono l’API completa – valori predefiniti del proprietario, concessioni per utente, voci di ruolo, flag pubblici – e l’applicazione delle regole avviene in Back4app su ogni richiesta REST, GraphQL e Live Query, così che le sottoscrizioni in tempo reale rispettino le stesse liste degli invitati delle query. Il modello a due barriere arriva intatto: i permessi di classe fissano la politica della categoria nella dashboard, le ACL per oggetto la affinano record per record e un’impostazione di ACL predefinita fa nascere i nuovi oggetti privati, riservati al proprietario. La scala delle mitigazioni è già integrata – i ruoli sono oggetti che si gestiscono come qualsiasi altro dato – lasciando le decisioni di progettazione, e non il macchinario di applicazione delle regole, come parte di lavoro da svolgere.
Domande frequenti
Che cos'è un'ACL, in parole semplici?
Una lista degli invitati allegata a ogni risorsa: indica chi può accedere a quell'oggetto preciso e che cosa ciascuno può farci – Ada legge e scrive, Bob può solo leggere, tutti gli altri restano fuori. La lista viaggia con l'oggetto, così ogni oggetto può avere regole proprie.
Che cos'è una voce di controllo degli accessi (ACE)?
Una riga della lista: un soggetto (un utente, un ruolo o "tutti") abbinato ai permessi che gli vengono concessi o negati. Un'ACL non è altro che una raccolta ordinata di ACE allegata a una sola risorsa.
Quali sono i tipi di ACL?
Tre famiglie condividono il nome: le ACL di rete (filtri ordinati del traffico su router e firewall), le ACL dei file system (liste di permessi per file che estendono proprietario/gruppo/altri) e le ACL applicative o di database (liste di permessi per record nello strato dei dati). Nello sviluppo backend si parla quasi sempre della terza.
Qual è la differenza tra ACL e RBAC?
Dove si agganciano i permessi. Un'ACL li appende a ogni risorsa, soggetto per soggetto – ideale quando i singoli oggetti richiedono decisioni singole. RBAC li appende ai ruoli e assegna gli utenti ai ruoli – ideale quando l'accesso segue la funzione lavorativa su molte risorse. I sistemi reali combinano i due approcci: i ruoli per le linee generali, le ACL per le eccezioni su singoli oggetti.
Come funzionano le ACL in un database?
Ogni riga o documento porta (o referenzia) la propria lista di permessi – di norma un campo ACL che associa ID utente e nomi di ruolo a flag di lettura/scrittura. Il database o il backend la valuta a ogni operazione, cosa che si combina naturalmente con la sicurezza a livello di riga e con gli strati di permessi per tabella.
Qual è la differenza tra un'ACL e una capability list?
Due viste della stessa matrice degli accessi: un'ACL è una colonna – memorizzata con l'oggetto, elenca i suoi soggetti – mentre una capability list è una riga, memorizzata con il soggetto, che elenca i suoi oggetti. Le ACL rendono immediatamente verificabile "chi può toccare questo oggetto?"; le capability facilitano "che cosa può toccare questo utente?", ma complicano la revoca.
Perché le ACL da sole non scalano?
Perché la contabilità cresce come oggetti × soggetti: ogni assunzione, uscita e riorganizzazione impone di modificare liste sparse su milioni di oggetti. Le mitigazioni sono le voci di ruolo (una sola ACE copre una popolazione che cambia), le ACL predefinite applicate alla creazione e le regole di classe che gestiscono il caso comune, così che le liste per oggetto coprano solo le eccezioni.
Qual è la differenza tra permessi per oggetto e permessi di classe?
La granularità. I permessi di classe (o di tabella) controllano un'intera categoria – "solo gli utenti autenticati possono interrogare Documents". Le ACL per oggetto controllano un singolo record – "solo Ada può leggere questo documento". I sistemi a strati verificano prima la barriera della classe, poi l'ACL dell'oggetto; una richiesta deve superarle entrambe.