Non avrei scelto di esprimere il commento originale nel modo in cui è stato formulato, ma identifica un problema legittimo potenzialmente .
In particolare, le preoccupazioni che giustificano la separazione sono autenticazione rispetto a autorizzazione .
Autenticazione fa riferimento al processo di accesso e acquisizione di un'identità. È come i sistemi sanno chi sei e sono usati per cose come personalizzazione, proprietà di oggetti, ecc.
Autorizzazione si riferisce a che cosa ti è permesso fare , e questo (generalmente) è non determinato da chi sei . Al contrario, è determinato da una politica di sicurezza come ruoli o permessi, a cui non importa nulla come il tuo nome o il tuo indirizzo email.
Questi due possono cambiare ortogonalmente l'un l'altro. Ad esempio, è possibile modificare il modello di autenticazione aggiungendo i provider OpenID / OpenAuth. E potresti cambiare la politica di sicurezza aggiungendo un nuovo ruolo o cambiando da RBAC a ABAC.
Se tutto questo va in una classe o in un'astrazione, allora il tuo codice di sicurezza, che è uno dei tuoi strumenti più importanti per mitigazione del rischio , diventa, ironicamente, ad alto rischio.
Ho lavorato con sistemi in cui l'autenticazione e l'autorizzazione erano troppo strettamente accoppiate. In un sistema, c'erano due database utente paralleli, ciascuno per un tipo di "ruolo". La persona o il team che l'ha progettata apparentemente non ha mai considerato che un singolo utente fisico potrebbe essere in entrambi i ruoli o che potrebbero esserci azioni comuni a più ruoli o che potrebbero esserci problemi con le collisioni ID utente. Questo è sicuramente un esempio estremo, ma era / è incredibilmente doloroso con cui lavorare.
Microsoft e Sun / Oracle (Java) si riferiscono al aggregato delle informazioni di autenticazione e autorizzazione come Security Principal . Non è perfetto, ma funziona abbastanza bene. In .NET, ad esempio, hai IPrincipal
, che incapsula il IIdentity
- il primo è un oggetto criterio (autorizzazione) mentre il secondo è un identità (autenticazione). Potresti ragionevolmente dubitare della decisione di mettere uno dentro dell'altro, ma la cosa importante è che la maggior parte del codice che scrivi sarà solo per una delle astrazioni che significa che è facile da testare e refactoring.
Non c'è niente di sbagliato in un campo User.IsAdmin
... a meno che non ci sia anche un campo User.Name
. Ciò indicherebbe che il concetto di "utente" non è propriamente definito e questo è, purtroppo, un errore molto comune tra gli sviluppatori che sono un po 'bagnati dietro le orecchie quando si parla di sicurezza. In genere, l'unica cosa che deve essere condivisa da identity e policy è l'ID utente, che, non a caso, è esattamente come viene implementato sia in Windows che in * nix modelli di sicurezza.
È completamente accettabile creare oggetti wrapper che incapsulino sia l'identità che la politica. Ad esempio, faciliterebbe la creazione di una schermata del dashboard in cui è necessario visualizzare un messaggio "ciao" oltre a vari widget o collegamenti a cui l'utente corrente può accedere. Finché questo wrapper racchiude solo le informazioni sull'identità e sulla politica e non pretende di possederlo. In altre parole, purché non venga presentato come una radice aggregata .
Un modello di sicurezza semplicistico sembra come una buona idea quando progetti per la prima volta una nuova applicazione, a causa di YAGNI e tutto il resto, ma finisce quasi sempre per tornare a morderti dopo, perché, sorpresa a sorpresa, vengono aggiunte nuove funzionalità!
Quindi, se sai cosa è meglio per te, manterrai le informazioni di autenticazione e autorizzazione separate. Anche se la "autorizzazione" adesso è semplice come un flag "IsAdmin", starai ancora meglio se non fa parte della stessa classe o tabella delle informazioni di autenticazione, in modo che se e quando la tua politica di sicurezza debba cambia, non hai bisogno di fare interventi di chirurgia ricostruttiva sui tuoi sistemi di autenticazione che funziona già bene.