Non avrei scelto di pronunciare il commento originale nel modo in cui è stato formulato, ma identifica un problema potenzialmente legittimo.
In particolare, le preoccupazioni che giustificano la separazione sono l' autenticazione e l' autorizzazione .
L'autenticazione si riferisce al processo di accesso e acquisizione di un'identità. È come i sistemi sanno chi sei e usato per cose come la personalizzazione, la proprietà degli oggetti, ecc.
L'autorizzazione si riferisce a ciò che ti è permesso fare e questo (generalmente) non è determinato da chi sei . Invece, è determinato da alcune politiche di sicurezza come ruoli o autorizzazioni, a cui non interessano cose come il tuo nome o indirizzo email.
Questi due possono cambiare ortogonalmente tra loro. Ad esempio, è possibile modificare il modello di autenticazione aggiungendo provider OpenID / OpenAuth. E potresti cambiare la politica di sicurezza aggiungendo un nuovo ruolo o passando da RBAC ad ABAC.
Se tutto ciò rientra in una classe o astrazione, il tuo codice di sicurezza, che è uno dei tuoi strumenti più importanti per la 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 lo ha progettato apparentemente non ha mai considerato che un singolo utente fisico potesse essere in entrambi i ruoli o che potrebbero esserci determinate azioni comuni a più ruoli o che potrebbero esserci problemi con le collisioni dell'ID utente. Questo è certamente un esempio estremo, ma è stato / è incredibilmente doloroso lavorare con.
Microsoft e Sun / Oracle (Java) si riferiscono all'aggregato delle informazioni di autenticazione e autorizzazione come Responsabile della sicurezza . Non è perfetto, ma funziona abbastanza bene. In .NET, ad esempio, hai IPrincipal
, che incapsula il IIdentity
primo essendo un oggetto policy (autorizzazione) mentre il secondo è un'identità (autenticazione). Potresti ragionevolmente mettere in dubbio la decisione di metterne uno dentro l'altro, ma la cosa importante è che la maggior parte del codice che scrivi sarà solo per una delle astrazioni, il che significa che è facile testare e refactoring.
Non c'è niente di sbagliato in un User.IsAdmin
campo ... a meno che non ci sia anche un User.Name
campo. Ciò indicherebbe che il concetto di "Utente" non è definito correttamente e questo è, purtroppo, un errore molto comune tra gli sviluppatori che sono un po 'bagnati dietro le orecchie quando si tratta di sicurezza. In genere, l'unica cosa che dovrebbe essere condivisa dall'identità e dalla politica è l'ID utente, che, non a caso, è esattamente come viene implementato nei modelli di sicurezza Windows e * nix.
È completamente accettabile creare oggetti wrapper che incapsulino identità e criteri. 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. Fintanto che questo wrapper avvolge solo le informazioni sull'identità e sulla politica e non pretende di possederlo. In altre parole, purché non sia presentato come radice aggregata .
Un modello di sicurezza semplicistico sembra sempre una buona idea quando si progetta per la prima volta una nuova applicazione, a causa di YAGNI e tutto il resto, ma quasi sempre finisce per tornare a morderti più tardi, perché, sorpresa sorpresa, vengono aggiunte nuove funzionalità!
Quindi, se sai cosa è meglio per te, manterrai le informazioni di autenticazione e autorizzazione separate. Anche se "l'autorizzazione" in questo momento è semplice come un flag "IsAdmin", starai comunque meglio se non fa parte della stessa classe o tabella delle informazioni di autenticazione, quindi se e quando la tua politica di sicurezza deve cambiare, non è necessario eseguire interventi di chirurgia ricostruttiva sui sistemi di autenticazione che funzionano già bene.