"Ho nascosto la voce 'Settings' dal menu degli utenti senza permessi. Sicurezza fatta!" → FALSO. Un utente con basi tecniche può accedere comunque modificando l'URL. La sicurezza dei permessi richiede doppio controllo: UI nasconde, backend rifiuta. Vediamo perché serve e come funziona.
L'errore comune
Sviluppatori junior pensano: "se non vede il menu, non può accedere".
Sbagliato. L'utente può:
- Modificare URL manualmente nel browser.
- Usare F12 (DevTools) per vedere route nascoste.
- Chiamare direttamente API endpoint.
- Usare Postman o curl per fare richieste.
- Modificare cookie/localStorage per simulare admin.
Se solo l'UI nasconde, ma il backend serve la richiesta, la sicurezza è zero.
Esempio di attacco
Scenario
Utente "tirocinante" con ruolo "view-only". Menu UI nasconde "Operazioni di Scrittura". Ma il backend non controlla.
Attacco
Tirocinante apre browser, va a:
https://reportia.azienda.it/admin/operazioni-scrittura
Pagina si apre. Tirocinante esegue DELETE distruttivi. Audit log registra ma il danno è fatto.
L'approccio corretto: doppia sicurezza
Layer 1: UI
Nascondi voci di menu, pulsanti, sezioni che l'utente non può usare.
Vantaggi:
- UX pulita.
- Niente confusione (vedo solo cosa posso fare).
- Riduce tentativi accidentali.
Limite: solo cosmetico. Non è sicurezza.
Layer 2: Backend
Ogni route, ogni API endpoint verifica permessi server-side prima di servire.
Codice tipico:
public function operazioniScrittura() {
if (!auth()->user()->hasPermission('reportia_operazioni_scrittura')) {
return abort(403, 'Permesso negato');
}
// logica...
}
Se l'utente non ha permesso, backend restituisce 403 Forbidden. UI nasconde + backend rifiuta = sicurezza vera.
Le 4 zone da proteggere
1. Route web (pagine)
Ogni URL deve verificare permessi. Esempio:
/admin/usersrichiede ruolo admin./operazioni-scritturarichiede permesso scrittura./audit-logrichiede permesso audit.
2. API endpoint (backend)
Ogni POST/GET/PUT/DELETE verifica:
- Token valido.
- Utente esistente.
- Utente attivo.
- Permesso specifico per quell'endpoint.
- Limit per dati: utente vede solo i propri.
3. Query database
Ogni query include filtro per id_azienda dell'utente. Anche se l'utente "passa" un id_azienda diverso, backend lo ignora.
4. File system
Download file: verifica che l'utente abbia accesso a quel file specifico.
Esempio in ReportIA
Per il modulo "Operazioni di Scrittura":
Frontend
- Voce "Operazioni Scrittura" nel menu solo se utente ha permesso.
- Pulsante "Esegui INSERT" disabilitato se senza permesso.
Backend (ogni endpoint)
- POST /api/scrittura/anteprima → verifica permesso.
- POST /api/scrittura/esegui → verifica permesso.
- GET /api/scrittura/audit → verifica permesso.
Validazione dati
- Tabelle whitelist: solo le ammesse possono essere modificate.
- Limit righe: max 100 per operazione.
- SQL injection prevention: prepared statements.
Audit log
- Anche tentativi falliti vengono loggati.
- Pattern di attacco rilevabili.
Test di sicurezza
Per verificare doppia sicurezza:
Test 1: utente senza permesso prova URL diretto
Dovrebbe ricevere 403 Forbidden.
Test 2: utente prova API con token modificato
Dovrebbe ricevere 401 Unauthorized.
Test 3: utente prova accesso a id_azienda diverso
Dovrebbe vedere solo dati della sua azienda.
Test 4: utente prova SQL injection
Prepared statements bloccano. Audit log registra tentativo.
Penetration test
Periodicamente (annualmente):
- Pen test esterno.
- Verifica che permessi non siano aggirabili.
- Test scenari attack.
- Report con eventuali vulnerabilità.
I moduli ReportIA correlati
Scopri ReportIA con doppia sicurezza nativa.