Por lo general, coloco las decisiones de autorización en los controladores del lado del servidor. Estos han sido puntos finales RESTful recientemente, pero creo que lo mismo se aplica a las arquitecturas de tipo MVC. Por razones de argumento, suponga que se trata de una autorización basada en roles. Se anotará un método protegido o se realizarán cheques y se devolverán 403 si es necesario.
Ahora, dado que la autorización es, de hecho, una regla comercial: "solo los administradores pueden enumerar X", por ejemplo, creo que deberían ser empujados hacia abajo una capa. Cuando un controlador solicita a la capa empresarial que realice la operación, el servicio o la capa empresarial informa al controlador que no está autorizado.
¿Es este un enfoque razonable? ¿Hay desventajas en esto?
Odio tener un AuthorisationService que esencialmente contenga un montón de reglas estáticas codificadas de procedimiento para hacer esto, pero tal vez tenga sentido mantener toda la lógica de acceso en un solo lugar. ¿Es una preocupación transversal que debe mantenerse separada?
Entonces, pregunto si alguien ha hecho esto y cómo lo lograron de manera limpia o si hay algún buen recurso que pueda leer. Estoy usando Java fwiw pero esta es una pregunta agnóstica de lenguaje.
He revisado las preguntas relacionadas aquí y son muy delgadas en el terreno y las respuestas. Por ejemplo: Validación y autorización en modelos de dominio y llevarlo a través de una capa de servicio a MVC
Estoy leyendo los documentos de seguridad de primavera que presentan algunos buenos argumentos para que sea una preocupación transversal, pero me preocupa que sea solo la "vía de la primavera" y me gustaría tener perspectivas más amplias. También vincula su aplicación a un marco específico.
fuente
Respuestas:
Es una buena práctica exponer solo las opciones para las que un usuario está autorizado.
Esto obliga a la autorización a ser una preocupación transversal. La "Vista" necesita saber qué puede hacer un usuario antes de poder crear opciones y menús para mostrar.
El back end no debe confiar en el front end para tomar decisiones de seguridad, por lo que debe verificar la autorización por sí mismo.
Es posible que existan reglas comerciales que afecten la autorización según los datos, por ejemplo, "Solo los usuarios con un saldo superior a $ 5000 pueden invocar una transferencia de moneda extranjera" o "Solo un usuario ubicado en la Oficina Central puede ver estas cuentas". Por lo tanto, se requiere cierta lógica de autorización dentro de la lógica empresarial.
También hay que tener en cuenta las autorizaciones técnicas: quién puede ver los registros, quién puede hacer una copia de seguridad / restaurar la base de datos, etc.
Por lo tanto, al final, cada componente en su cuenta puede tener algunos requisitos específicos de seguridad y / o autorización, en la práctica es casi imposible resumir esto en una "capa de autorización" separada.
fuente
Creo que es un enfoque absolutamente razonable para autorizar el grabado en su capa de Servicio. Debe proteger su servicio para que no realice actividades no autorizadas (especialmente modificaciones de datos). Su capa de Servicio podría residir en una biblioteca y ser utilizada por diferentes capas de Presentación (podría tener diferentes aplicaciones de IU, que usan la misma capa de Servicio). Y no puede confiar en el hecho de que las capas de presentación específicas realizan la validación necesaria. Esto es especialmente importante si luego decide trasladar su capa de Servicio al proceso separado (por ejemplo, siguiendo el enfoque SOA).
Ahora sobre cómo lograr esto de una "manera limpia". No me gusta la idea de ensuciar la lógica empresarial con verificaciones de autorización, por lo que podría ayudar alguna implementación específica del enfoque de programación orientada a aspectos: podría ser decorar métodos de servicio con atributos especiales o usar proxies dinámicos con intercepciones.
Y lo que es más importante, debo admitir que en proyectos muy simples, puede ser, podrías vivir sin validaciones separadas, solo para simplificar tu vida. Pero es importante no perderse el momento en que "proyecto simple" comenzó a convertirse en "proyecto complejo".
fuente
¡Me gusta bajar los cheques de autorización lo más bajo posible! (¡Pero no más!)
Todavía puede escribir pruebas de autorización automatizadas en capas "por encima" de esto. Y algunas reglas solo pueden ser aplicables o tener sentido en capas superiores como su capa de servicio (CanView / CanSerialize?). Pero, en general, creo que la estrategia de autorización más segura también es la estrategia "DRY-est": mantenga la autorización lo más baja posible, en el código más "común" o "compartido" que pueda (sin complicar demasiado las reglas de autenticación).
Piensa en la alternativa. Si sus reglas de autorización se prueban y aplican solo en la capa de servicio, dejando que sus objetos de dominio pobres se doblen a la voluntad de un objeto de servicio cambiante, a menudo se le pedirá que aplique cada regla individual más de una vez, en múltiples objetos y múltiples lugares en cada objeto, y en código más complicado.
Además, cuando su equipo de análisis contrata a una empresa de consultoría para escribir servicios de informes utilizando sus objetos de dominio, ¡no querrá tener que confiar en esos desarrolladores! (O lo que sea. Cree servicios o llamadas adicionales sobre los mismos objetos por cualquier motivo). No querrá abrir el gran libro de reglas comerciales y esperar hacer cumplir esas reglas nuevamente ; desea que su dominio ya los conozca y los haga cumplir.
fuente
Widget
, la misma regla se aplica en todas partes. (¡Así que no se arriesgue a que nadie lo ignore!) Si la regla no se aplica en todas partes, en realidad no es una reglaWidgets
y soloWidgets
. . Empuje las reglas hacia abajo hasta donde puedan llegar (las reglas individuales); pero, no tan lejos como las "reglas" pueden llegar ... Siento que no estoy afirmando bien la distinción. Pero, se supone que debe haber distinción allí.