¿Dónde encaja la autorización en una arquitectura en capas?

24

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.

tom
fuente
1
El estado 403 es incorrecto por problemas de autorización. Use 401.
gnasher729
@ gnasher729 Creo que está al revés. 401 significa que la autenticación ha fallado o no se proporciona, 403 significa que no tiene derechos de acceso: stackoverflow.com/questions/3297048/…
JimmyJames
@JimmyJames, hay otra escuela de pensamiento que debería usar solo uno de ellos para todas las fallas de autenticación y autorización, ya que no permite que las herramientas automatizadas infieran la lógica empresarial tan fácilmente. Hay algo de margen.
Berin Loritsch
1
@BerinLoritsch Lo sentimos, ¿estás diciendo que la idea es hacer que sea más difícil de entender si se trata de un problema de autenticación o autorización? El RFC parece bastante claro, pero establece que puede usar 404 en lugar de 403 si no desea exponer demasiada información. ¿Hay alguna referencia que pueda proporcionar para el argumento de usar un 401 en lugar de 403?
JimmyJames
@JimmyJames, sí. Este proceso de pensamiento proviene de profesionales de la seguridad, no de desarrolladores. Y también he visto su recomendación de 404 para ocultar completamente la información para ocultar que el recurso incluso existe.
Berin Loritsch

Respuestas:

9

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.

James Anderson
fuente
7

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".

ialekseev
fuente
7

¡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.

svidgen
fuente
@Shoe Si entiendo tu preocupación, ese es el punto. Si solo un "administrador" tiene permiso, de acuerdo con las reglas comerciales, para crear una 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 regla Widgetsy solo Widgets . . 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í.
svidgen
En mi experiencia, las reglas de autorización son a menudo parte de las reglas comerciales. Como tal, "tan lejos como pueden llegar" es a menudo mi capa de dominio. Pero sospecho que el lugar donde sus reglas "deberían" caer es solo una consecuencia de su dominio, la naturaleza de las reglas y la forma en que el negocio habla de ellas.
svidgen