No hubiera elegido redactar el comentario original de la forma en que estaba redactado, pero identifica un problema legítimo potencialmente .
Específicamente, las preocupaciones que justifican la separación son autenticación frente a autorización .
Autenticación se refiere al proceso de inicio de sesión y obtención de una identidad. Es así como los sistemas saben quién eres y se usan para cosas como personalización, propiedad de objetos, etc.
Autorización se refiere a lo que se te permite hacer , y esto (generalmente) no está ni determinado por quién eres . En su lugar, está determinada por alguna política de seguridad como roles o permisos, que no se preocupa por cosas como su nombre o dirección de correo electrónico.
Estos dos pueden cambiar ortogonalmente entre sí. Por ejemplo, puede cambiar el modelo de autenticación agregando proveedores de OpenID / OpenAuth. Y puede cambiar la política de seguridad agregando una nueva función o cambiando de RBAC a ABAC.
Si todo esto entra en una clase o abstracción, entonces su código de seguridad, que es una de sus herramientas más importantes para mitigar el riesgo , se convierte, irónicamente, en alto riesgo.
He trabajado con sistemas en los que la autenticación y la autorización estaban demasiado vinculadas. En un sistema, había dos bases de datos de usuarios paralelas, cada una para un tipo de "función". La persona o el equipo que lo diseñó aparentemente nunca consideró que un solo usuario físico pudiera estar en ambos roles, o que podría haber ciertas acciones que fueran comunes a múltiples roles, o que podría haber problemas con las colisiones de ID de usuario. Este es un ejemplo ciertamente extremo, pero fue / es increíblemente doloroso trabajar con él.
Microsoft y Sun / Oracle (Java) se refieren al agregado de la información de autenticación y autorización como Director de seguridad . No es perfecto, pero funciona razonablemente bien. En .NET, por ejemplo, tiene IPrincipal
, que encapsula el IIdentity
- el primero es un objeto policy (autorización) mientras que el último es un identidad (autenticación). Podría cuestionar razonablemente la decisión de poner uno dentro del otro, pero lo importante es que la mayoría del código que escriba será solo para una de las abstracciones , lo que significa que es Fácil de probar y refactorizar.
No hay nada de malo en el campo User.IsAdmin
... a menos que también haya un campo User.Name
. Esto indicaría que el concepto "Usuario" no está correctamente definido y esto es, lamentablemente, un error muy común entre los desarrolladores que están un poco mojados detrás de las orejas cuando se trata de seguridad. Por lo general, lo único que debe ser compartido por identidad y política es el ID de usuario, que, no por casualidad, es exactamente cómo se implementa tanto en Windows como en * nix modelos de seguridad.
Es completamente aceptable crear objetos de envoltura que encapsulan identidad y política. Por ejemplo, facilitaría la creación de una pantalla de panel de control en la que deba mostrar un mensaje de "saludo" además de varios widgets o enlaces a los que el usuario actual puede acceder. Siempre y cuando este envoltorio simplemente ajuste la información de identidad y política, y no pretenda poseerlo. En otras palabras, siempre que no se presente como una raíz agregada .
Un modelo de seguridad simplista siempre parece como una buena idea cuando estás diseñando una nueva aplicación, debido a YAGNI y todo eso, pero casi siempre termina volviéndote a morder después. porque, sorpresa sorpresa, se agregan nuevas funciones!
Entonces, si sabe qué es lo mejor para usted, mantendrá la información de autenticación y autorización por separado. Incluso si la "autorización" en este momento es tan simple como un indicador "IsAdmin", todavía estará mejor si no es parte de la misma clase o tabla que la información de autenticación, de modo que, si y cuando su política de seguridad necesite Cambie, no necesita realizar una cirugía reconstructiva en sus sistemas de autenticación, que ya funciona bien.