No hubiera elegido redactar el comentario original de la forma en que fue redactado, pero identifica un problema potencialmente legítimo.
Específicamente, las preocupaciones que justifican la separación son autenticación versus autorización .
La autenticación se refiere al proceso de iniciar sesión y obtener una identidad. Es la forma en que los sistemas saben quién es usted y cómo se utilizan para cosas como personalización, propiedad de objetos, etc.
La autorización se refiere a lo que tiene permitido hacer , y esto (generalmente) no está determinado por quién es usted . En cambio, está determinado por alguna política de seguridad como roles o permisos, que no se preocupan 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 OpenID / OpenAuth. Y puede cambiar la política de seguridad agregando un nuevo rol 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 la mitigación de riesgos , se convierte, irónicamente, en de alto riesgo.
He trabajado con sistemas en los que la autenticación y la autorización estaban demasiado unidas. En un sistema, había dos bases de datos de usuarios paralelas, cada una para un tipo de "rol". Aparentemente, la persona o el equipo que lo diseñó nunca consideró que un solo usuario físico podría tener ambos roles, o que podría haber ciertas acciones que eran 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 conjunto de información de autenticación y autorización como Principal de seguridad . No es perfecto, pero funciona razonablemente bien. En .NET, por ejemplo, tiene IPrincipal
, que encapsula el IIdentity
- el primero es un objeto de política (autorización) mientras que el segundo es una identidad (autenticación). Podría cuestionar razonablemente la decisión de colocar 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 un User.IsAdmin
campo ... a menos que también haya un User.Name
campo. Esto indicaría que el concepto de "Usuario" no está bien definido y este 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 compartir la identidad y la política es la ID de usuario, que, no por coincidencia, es exactamente cómo se implementa en los modelos de seguridad de Windows y * nix.
Es completamente aceptable crear objetos de contenedor que encapsulen tanto la identidad como la política. Por ejemplo, facilitaría la creación de una pantalla de tablero en la que necesita mostrar un mensaje de "saludo" además de varios widgets o enlaces a los que el usuario actual tiene permitido acceder. Siempre que este contenedor solo envuelva la información de identidad y política, y no afirme ser el propietario. En otras palabras, siempre que no se presente como una raíz agregada .
Un modelo de seguridad simplista siempre parece una buena idea cuando diseñas una nueva aplicación por primera vez, debido a YAGNI y todo eso, pero casi siempre termina volviendo a morderte más tarde, porque, sorpresa sorpresa, ¡se agregan nuevas funciones!
Entonces, si sabe lo que es 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", aún así será 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.