¿Cómo gestionar permisos en Spring para que los usuarios realicen ciertas acciones?
La gestión de permisos en una aplicación es fundamental para garantizar la seguridad y correcta operación de los servicios, especialmente en aplicaciones web donde diferentes usuarios pueden requerir distintos niveles de acceso. En el contexto de aplicaciones Spring, el uso de Authorities y Roles es clave para la implementación de esta funcionalidad. Exploremos cómo se utiliza Spring Security para definir permisos específicos que permiten a los usuarios ejecutar determinado tipo de acciones de acuerdo a su rol.
¿Cuál es la diferencia entre Authorities y Roles?
En Spring Security, las Authorities y Roles aunque a primera vista podrían parecer similares, poseen diferencias cruciales:
Roles: Son grupos de permisos que un usuario puede tener. Un rol puede agrupar varios permisos, facilitando la gestión de permisos de usuarios que realizan funciones similares.
Authorities: Son permisos específicos que un usuario puede tener para ejecutar acciones concretas dentro de la aplicación. A diferencia de los roles, son más granulares y permiten asignar permisos muy específicos.
Spring asigna automáticamente el prefijo "ROLE" para diferenciar un rol de una autoridad.
¿Cómo implementar Roles y Authorities en Spring?
La implementación de roles y autoridades se realiza mediante el uso de clases de seguridad que artículen la creación y asignación de estos permisos. El proceso es el siguiente:
Creación de una Lista de Authorities: Se crea un método privado que retorna una lista de GrantedAuthority. Este método recibirá roles que tiene el usuario previamente.
privateList<GrantedAuthority>grantedAuthorities(String[] roles){List<GrantedAuthority> authorities =newArrayList<>(roles.length);for(String role : roles){ authorities.add(newSimpleGrantedAuthority("ROLE_"+ role));}return authorities;}
Asignación de Permisos Individuales: Además de roles, se pueden asignar permisos individuales a través de un método que retorne un arreglo de strings con los permisos específicos.
¿Por qué es crucial el orden de las reglas de seguridad?
Es vital tener en cuenta el orden en que se evalúan las reglas de seguridad, ya que se ejecutan de forma escalonada. Si una regla general en la lista impide el acceso a un recurso basado en el rol, ninguna otra regla específica de permiso será evaluada después:
La regla que permita permisos específicos debe estar posicionada antes de reglas más generales. Por ejemplo, permitir a un authority específico acceder a un endpoint antes de denegar acceso a roles que no cumplan otros criterios.
¿Qué sucede si se comete un error en el orden?
Al ejecutarse las reglas de seguridad de arriba hacia abajo, un error en el orden puede impedir que un usuario, que debiera tener acceso a una función específica, lo tenga.
Intentar realizar una acción con un usuario con un rol incorrecto resultará en un error del tipo 403 Forbidden, indicando que las credenciales no son suficientes para completar la acción.
Al aplicar estos conceptos, puedes crear usuarios con permisos adaptados a sus necesidades específicas. Usar roles para permiso generales y authorities para quienes necesitan funcionalidades más expresas es una manera eficaz de mejorar la seguridad en tus aplicaciones Spring.
Se entiende como un rol un conjunto de authorities. Es decir, un autority es un permiso puntual mientras un rol un conjunto de permisos.
Un rol puede tener estos permisos de manera conceptual, sin tener que especificar cada authority en el código.
Rol: Acceso a un Modulo(s)
Authorities: Permiso puntual sobre el modulo.
i.e;
El rol Admin tiene acceso al modulo alta de usuarios,
y con los authorities puede crear editar, borrar usuarios.
Un Rol Supervisor, tiene acceso al modulo alta de usuarios, pero con los authorities puede editar solamente usuarios.
si mi proyecto es muy grande, y manejo varios roles, como se deberian de gestionar todas las authorities? todo en el userDetailsService?, lo mismo con los requestMatcher, si tengo muchisimos, todo va en el el filterChain?
Los Authorities también deberían estar almacenados en mi base de datos?
En mi opinión creo que depende de la complejidad de tu aplicación, pero en general es innecesario, en el caso de los roles se hizo porque un usuario puede tener muchos roles, y usuarios pueden haber muchos, en el caso de las Authorities estarán únicamente relacionadas con los roles, los cuales sí que pueden ser limitados (4 o 5 roles en la app), no muchos, lo cual se puede escribir directamente en código como se hace en el video.
Body de ejemplo para consumir el endpoint localhost:8080/api/orders/random
{
"idCustomer": "192758012",
"method": "D"
}
gracias , lo andaba buscando
Para aplicar authorities a los usuarios en Spring Security, debes diferenciar entre roles y authorities. Los roles son conjuntos de permisos, mientras que las authorities representan permisos individuales.
Primero, crea un método que asigne authorities a los usuarios utilizando GrantedAuthority. Esto implica transformar tus roles en una lista de SimpleGrantedAuthority. Por ejemplo, puedes usar hasAuthority("randomOrder") en tu configuración de seguridad para permitir accesos específicos a usuarios.
Es esencial establecer el orden correcto de las reglas en tu configuración de seguridad para evitar bloqueos innecesarios.
Nuevo usuario chef que no esta dentro de la condición para tener el authority "random_order":
hay forma de validar la autorización desde otro microservicio?
yo tengo dos microservicios, uno para el login de usuarios y autorización, y otro para gestion de productos, ¿yo puedo validar la autorización desde el microserviciode gestión de productos contra el micro servicio de seguridad?
Lo que entendi sobre los roles y authorities, ejemplo:
Rol: "ADMIN" (agrupa varias authorities)
Authority: "CREATE_USER"
Authority: "DELETE_USER"
Authority: "RANDOM_ORDER"
✅
Estoy tratando de ejectutar /api/orders/random pero no he podido por que me manda un error, creo que en el sql no viene incluido la rutina para la creacionde StoreProcedure take_random_pizza_order
Hola, seria más facil si dejas el error puntual de la consola. Si estas trabajando con mySQL crea y ejecuta un scrip con el siguiente código para crear el procedimiento en la base de datos:
DROP procedure IFEXISTS`take_random_pizza_order`;DELIMITER $$
CREATEPROCEDURE`take_random_pizza_order`(IN id_customer VARCHAR(15),IN method CHAR(1),OUT order_taken bool)BEGIN # Declara las variables para:DECLARE id_random_pizza INT; # tomar un id de pizza al azar
DECLARE price_random_pizza DECIMAL(5,2); # Precio de la pizza
DECLARE price_with_discount DECIMAL(5,2); # Precio de la pizza con descuento
# Control de errores en caso de un error se hace un roll back
DECLAREWITH_ERRORSBOOLDEFAULTFALSE;DECLARECONTINUEHANDLERFORSQLEXCEPTIONBEGINSETWITH_ERRORS=TRUE;END; # Selecciona de la tabla pizza una pizza de manera aleatoria
SELECT id_pizza, price
INTO id_random_pizza, price_random_pizza
FROM pizza
WHERE available =1ORDERBYRAND()LIMIT1; # De la tabla seleccionada calcula el precio con descuento
SET price_with_discount = price_random_pizza -(price_random_pizza *0.20); # Se inicia a agregar los registros en la base de datos
STARTTRANSACTION;INSERTINTOpizza_order(id_customer, date, total, method, additional_notes)VALUES(id_customer,SYSDATE(), price_with_discount, method,'20% OFF PIZZA RANDOM PROMOTION'); # Esto hace que solo sea valido para una sola pizza
INSERTINTOorder_item(id_item, id_order, id_pizza, quantity, price)VALUES(1,LAST_INSERT_ID(), id_random_pizza,1, price_random_pizza); # Si el proceso es ok o con error inidica que valor se retorna
IFWITH_ERRORSTHENSET order_taken =FALSE;ROLLBACK;ELSESET order_taken =TRUE;COMMIT;ENDIF; # Retornamos el valor que es un boolean
SELECT order_taken;END$$
DELIMITER;