En Fundeweb 2 se ha realizado una implementación de la estructura de autorización para disponer de ella desde el inicio de nuestros proyectos, de manera que no tengamos que hacer un gran esfuerzo a la hora de implementar por completo toda la infraestructura, sino que partamos de una base sólida que podamos ampliar y/o modificar.
Esta estructura de autorización se basa en la propuesta en Gestión de Roles y Usuarios con tablas de Base de Datos creando una capa por encima con la funcionalidad necesaria para realizar la gestión básica de usuarios y permisos. Dejando como responsabilidad de los diferentes programadores la interpretación concreta de cada uno de esos permisos.
Como nota, del esquema de base de datos se puede deducir que la estructura de roles puede ser jerárquica, permitiendo tener roles y subroles y acumulando los permisos asociados a ellos.
Este es el script que genera este diagrama de tablas, parausarlo hay que sustituir [MIESQUEMA] por el nombre de nuestro esquema BBDD.
CREATE TABLE [MIESQUEMA].USUARIOS ( LOGIN VARCHAR2(40 BYTE) NOT NULL ) TABLESPACE [MIESQUEMA] RESULT_CACHE (MODE DEFAULT) PCTUSED 0 PCTFREE 10 INITRANS 1 MAXTRANS 255 STORAGE ( INITIAL 16K NEXT 128K MAXSIZE UNLIMITED MINEXTENTS 1 MAXEXTENTS UNLIMITED PCTINCREASE 0 BUFFER_POOL DEFAULT FLASH_CACHE DEFAULT CELL_FLASH_CACHE DEFAULT ) LOGGING NOCOMPRESS NOCACHE NOPARALLEL MONITORING; CREATE UNIQUE INDEX [MIESQUEMA].USUARIOS_PK ON [MIESQUEMA].USUARIOS (LOGIN) LOGGING TABLESPACE IND[MIESQUEMA] PCTFREE 10 INITRANS 2 MAXTRANS 255 STORAGE ( INITIAL 32K NEXT 32K MAXSIZE UNLIMITED MINEXTENTS 1 MAXEXTENTS UNLIMITED PCTINCREASE 0 BUFFER_POOL DEFAULT FLASH_CACHE DEFAULT CELL_FLASH_CACHE DEFAULT ) NOPARALLEL; ALTER TABLE [MIESQUEMA].USUARIOS ADD ( CONSTRAINT PK_USUARIOS PRIMARY KEY (LOGIN) USING INDEX [MIESQUEMA].USUARIOS_PK ENABLE VALIDATE); GRANT DELETE, INSERT, SELECT, UPDATE ON [MIESQUEMA].USUARIOS TO JV_[MIESQUEMA]; CREATE TABLE [MIESQUEMA].ROLES ( ID_ROL VARCHAR2(20 BYTE) NOT NULL, DESCRIPCION VARCHAR2(50 BYTE), ROL_PADRE VARCHAR2(20 BYTE) ) TABLESPACE [MIESQUEMA] RESULT_CACHE (MODE DEFAULT) PCTUSED 0 PCTFREE 10 INITRANS 1 MAXTRANS 255 STORAGE ( INITIAL 16K NEXT 128K MAXSIZE UNLIMITED MINEXTENTS 1 MAXEXTENTS UNLIMITED PCTINCREASE 0 BUFFER_POOL DEFAULT FLASH_CACHE DEFAULT CELL_FLASH_CACHE DEFAULT ) LOGGING NOCOMPRESS NOCACHE NOPARALLEL MONITORING; CREATE UNIQUE INDEX [MIESQUEMA].ROLES_PK ON [MIESQUEMA].ROLES (ID_ROL) LOGGING TABLESPACE IND[MIESQUEMA] PCTFREE 10 INITRANS 2 MAXTRANS 255 STORAGE ( INITIAL 32K NEXT 32K MAXSIZE UNLIMITED MINEXTENTS 1 MAXEXTENTS UNLIMITED PCTINCREASE 0 BUFFER_POOL DEFAULT FLASH_CACHE DEFAULT CELL_FLASH_CACHE DEFAULT ) NOPARALLEL; ALTER TABLE [MIESQUEMA].ROLES ADD ( CONSTRAINT PK_ROLES PRIMARY KEY (ID_ROL) USING INDEX [MIESQUEMA].ROLES_PK ENABLE VALIDATE); ALTER TABLE [MIESQUEMA].ROLES ADD ( CONSTRAINT ROLES_R01 FOREIGN KEY (ROL_PADRE) REFERENCES [MIESQUEMA].ROLES (ID_ROL) ENABLE VALIDATE); GRANT DELETE, INSERT, SELECT, UPDATE ON [MIESQUEMA].ROLES TO JV_[MIESQUEMA]; CREATE TABLE [MIESQUEMA].OBJETIVOS ( ID_OBJETIVO VARCHAR2(20 BYTE) NOT NULL, DESC_OBJETIVO VARCHAR2(50 BYTE) ) TABLESPACE [MIESQUEMA] RESULT_CACHE (MODE DEFAULT) PCTUSED 0 PCTFREE 10 INITRANS 1 MAXTRANS 255 STORAGE ( INITIAL 64K NEXT 1M MAXSIZE UNLIMITED MINEXTENTS 1 MAXEXTENTS UNLIMITED PCTINCREASE 0 BUFFER_POOL DEFAULT FLASH_CACHE DEFAULT CELL_FLASH_CACHE DEFAULT ) LOGGING NOCOMPRESS NOCACHE NOPARALLEL MONITORING; CREATE UNIQUE INDEX [MIESQUEMA].OBJETIVOS_PK ON [MIESQUEMA].OBJETIVOS (ID_OBJETIVO) LOGGING TABLESPACE IND[MIESQUEMA] PCTFREE 10 INITRANS 2 MAXTRANS 255 STORAGE ( INITIAL 64K NEXT 1M MAXSIZE UNLIMITED MINEXTENTS 1 MAXEXTENTS UNLIMITED PCTINCREASE 0 BUFFER_POOL DEFAULT FLASH_CACHE DEFAULT CELL_FLASH_CACHE DEFAULT ) NOPARALLEL; ALTER TABLE [MIESQUEMA].OBJETIVOS ADD ( CONSTRAINT OBJETIVOS_PK PRIMARY KEY (ID_OBJETIVO) USING INDEX [MIESQUEMA].OBJETIVOS_PK ENABLE VALIDATE); GRANT DELETE, INSERT, SELECT, UPDATE ON [MIESQUEMA].OBJETIVOS TO JV_[MIESQUEMA]; CREATE TABLE [MIESQUEMA].USUARIOS_ROLES ( COD_ROL VARCHAR2(3 BYTE) NOT NULL, COD_USUARIO VARCHAR2(10 BYTE) ) TABLESPACE [MIESQUEMA] RESULT_CACHE (MODE DEFAULT) PCTUSED 0 PCTFREE 10 INITRANS 1 MAXTRANS 255 STORAGE ( INITIAL 16K NEXT 128K MAXSIZE UNLIMITED MINEXTENTS 1 MAXEXTENTS UNLIMITED PCTINCREASE 0 BUFFER_POOL DEFAULT FLASH_CACHE DEFAULT CELL_FLASH_CACHE DEFAULT ) LOGGING NOCOMPRESS NOCACHE NOPARALLEL MONITORING; CREATE UNIQUE INDEX [MIESQUEMA].USUARIOS_ROLES_ROL ON [MIESQUEMA].USUARIOS_ROLES (COD_ROL, COD_USUARIO) LOGGING TABLESPACE IND[MIESQUEMA] PCTFREE 10 INITRANS 2 MAXTRANS 255 STORAGE ( INITIAL 32K NEXT 32K MAXSIZE UNLIMITED MINEXTENTS 1 MAXEXTENTS UNLIMITED PCTINCREASE 0 BUFFER_POOL DEFAULT FLASH_CACHE DEFAULT CELL_FLASH_CACHE DEFAULT ) NOPARALLEL; CREATE INDEX [MIESQUEMA].FK_USU ON [MIESQUEMA].USUARIOS_ROLES (COD_USUARIO) LOGGING TABLESPACE IND[MIESQUEMA] PCTFREE 0 INITRANS 2 MAXTRANS 255 STORAGE ( INITIAL 16K NEXT 16K MAXSIZE UNLIMITED MINEXTENTS 1 MAXEXTENTS UNLIMITED PCTINCREASE 0 BUFFER_POOL DEFAULT FLASH_CACHE DEFAULT CELL_FLASH_CACHE DEFAULT ) NOPARALLEL; ALTER TABLE [MIESQUEMA].USUARIOS_ROLES ADD ( CONSTRAINT PK_USUARIOS_ROLES PRIMARY KEY (COD_ROL, COD_USUARIO) USING INDEX [MIESQUEMA].USUARIOS_ROLES_ROL ENABLE VALIDATE); ALTER TABLE [MIESQUEMA].USUARIOS_ROLES ADD ( CONSTRAINT FK_ROL FOREIGN KEY (COD_ROL) REFERENCES [MIESQUEMA].ROLES (ID_ROL) ON DELETE CASCADE ENABLE VALIDATE, CONSTRAINT FK_USU FOREIGN KEY (COD_USUARIO) REFERENCES [MIESQUEMA].USUARIOS (LOGIN) ON DELETE CASCADE ENABLE NOVALIDATE); GRANT DELETE, INSERT, SELECT, UPDATE ON [MIESQUEMA].USUARIOS_ROLES TO JV_[MIESQUEMA]; CREATE TABLE [MIESQUEMA].ROLES_USUARIO ( ID_ROL VARCHAR2(20 BYTE) NOT NULL, LOGIN VARCHAR2(30 BYTE) NOT NULL, ID_ROL_USU NUMBER(19) NOT NULL ) TABLESPACE [MIESQUEMA] RESULT_CACHE (MODE DEFAULT) PCTUSED 0 PCTFREE 10 INITRANS 1 MAXTRANS 255 STORAGE ( INITIAL 64K NEXT 1M MAXSIZE UNLIMITED MINEXTENTS 1 MAXEXTENTS UNLIMITED PCTINCREASE 0 BUFFER_POOL DEFAULT FLASH_CACHE DEFAULT CELL_FLASH_CACHE DEFAULT ) LOGGING NOCOMPRESS NOCACHE NOPARALLEL MONITORING; CREATE UNIQUE INDEX [MIESQUEMA].ROLES_USUARIO_PK ON [MIESQUEMA].ROLES_USUARIO (ID_ROL_USU) LOGGING TABLESPACE IND[MIESQUEMA] PCTFREE 10 INITRANS 2 MAXTRANS 255 STORAGE ( INITIAL 64K NEXT 1M MAXSIZE UNLIMITED MINEXTENTS 1 MAXEXTENTS UNLIMITED PCTINCREASE 0 BUFFER_POOL DEFAULT FLASH_CACHE DEFAULT CELL_FLASH_CACHE DEFAULT ) NOPARALLEL; ALTER TABLE [MIESQUEMA].ROLES_USUARIO ADD ( CONSTRAINT ROLES_USUARIO_PK PRIMARY KEY (ID_ROL_USU) USING INDEX [MIESQUEMA].ROLES_USUARIO_PK ENABLE VALIDATE); ALTER TABLE [MIESQUEMA].ROLES_USUARIO ADD ( CONSTRAINT ROLES_USUARIO_R01 FOREIGN KEY (ID_ROL) REFERENCES [MIESQUEMA].ROLES (ID_ROL) ENABLE VALIDATE); GRANT DELETE, INSERT, SELECT, UPDATE ON [MIESQUEMA].ROLES_USUARIO TO JV_[MIESQUEMA]; CREATE TABLE [MIESQUEMA].ROLES_OBJETIVOS ( ID NUMBER NOT NULL, ID_ROL VARCHAR2(20 BYTE) NOT NULL, ID_OBJETIVO VARCHAR2(20 BYTE) NOT NULL, ACCION VARCHAR2(20 BYTE) NOT NULL ) TABLESPACE [MIESQUEMA] RESULT_CACHE (MODE DEFAULT) PCTUSED 0 PCTFREE 10 INITRANS 1 MAXTRANS 255 STORAGE ( INITIAL 64K NEXT 1M MAXSIZE UNLIMITED MINEXTENTS 1 MAXEXTENTS UNLIMITED PCTINCREASE 0 BUFFER_POOL DEFAULT FLASH_CACHE DEFAULT CELL_FLASH_CACHE DEFAULT ) LOGGING NOCOMPRESS NOCACHE NOPARALLEL MONITORING; CREATE UNIQUE INDEX [MIESQUEMA].ROLES_OBJETIVOS_PK ON [MIESQUEMA].ROLES_OBJETIVOS (ID) LOGGING TABLESPACE IND[MIESQUEMA] PCTFREE 10 INITRANS 2 MAXTRANS 255 STORAGE ( INITIAL 64K NEXT 1M MAXSIZE UNLIMITED MINEXTENTS 1 MAXEXTENTS UNLIMITED PCTINCREASE 0 BUFFER_POOL DEFAULT FLASH_CACHE DEFAULT CELL_FLASH_CACHE DEFAULT ) NOPARALLEL; ALTER TABLE [MIESQUEMA].ROLES_OBJETIVOS ADD ( CONSTRAINT ROLES_OBJETIVOS_PK PRIMARY KEY (ID) USING INDEX [MIESQUEMA].ROLES_OBJETIVOS_PK ENABLE VALIDATE); ALTER TABLE [MIESQUEMA].ROLES_OBJETIVOS ADD ( CONSTRAINT ROLES_OBJETIVOS_R01 FOREIGN KEY (ID_ROL) REFERENCES [MIESQUEMA].ROLES (ID_ROL) ENABLE VALIDATE, CONSTRAINT ROLES_OBJETIVOS_R02 FOREIGN KEY (ID_OBJETIVO) REFERENCES [MIESQUEMA].OBJETIVOS (ID_OBJETIVO) ENABLE VALIDATE); GRANT DELETE, INSERT, SELECT, UPDATE ON [MIESQUEMA].ROLES_OBJETIVOS TO JV_[MIESQUEMA]; CREATE SEQUENCE [MIESQUEMA].ROL_OBJETIVO_SEQ START WITH 0 MAXVALUE 9999999999999999999999999999 MINVALUE 0 NOCYCLE NOCACHE NOORDER; GRANT SELECT ON [MIESQUEMA].ROL_OBJETIVO_SEQ TO JV_[MIESQUEMA]; CREATE SEQUENCE [MIESQUEMA].ROL_USUARIO_SEQ START WITH 0 MAXVALUE 9999999999999999999999999999 MINVALUE 0 NOCYCLE NOCACHE NOORDER; GRANT SELECT ON [MIESQUEMA].ROL_USUARIO_SEQ TO JV_[MIESQUEMA];
Una vez con el esquema de base de datos creado, estamos en disposición de cargar las clases y vistas que harán posible tener nuestra infraestructura de autorización. Para ello tenemos dos opciones:
Una vez tengamos el código fuente, la aplicación podrá dar de alta usuarios y asignarle roles. Estos roles tendrán asociados a su vez objetivos y acciones que también podrán ser dados de alta desde la aplicación.
Por parte del programador queda implementar la parte que da sentido a los permisos partiendo del siguiente código base:
@Name("org.jboss.seam.security.identity") @Scope(ScopeType.SESSION) @Install(precedence = Install.APPLICATION, classDependencies = "org.umu.atica.servicios.gesper.gente.entity.Persona") @BypassInterceptors @Startup public class AplicacionIdentity extends UmuIdentity { private static final long serialVersionUID = 4315185968632267803L; @Override public boolean hasPermission(Object objetivo, String accion) { if (hasRole("ADMIN")) { return true; } else { return super.hasPermission(objetivo, accion); } } }
Una vez preparado todo desplegamos el código y accedemos a la sección de gestión de usuarios. En ella tendremos cuatro pestañas para gestionar todo lo concerniente a la autorización, roles y permisos de los mismos.
A continuación comentamos las diferentes pestañas:
Esta pestaña será la que nos permita la creación/edición de usuarios y asignación/eliminación de sus respectivos roles.
En esta pestaña podremos crear un nuevo usuario, para ello introduciremos su correo,nombre o apellidos y le daremos al botón buscar. Éste cargará un listado de todos los usuarios UMU que cumplen con el filtro establecido. Una vez obtenido el listado, seleccionaremos el usuario al que queramos dar de alta.
Una vez hecho esto buscamos al usuario en la tabla de usuarios y hacemos clic sobre él para gestionar sus roles que aparecerán en forma de árbol a la derecha de la tabla. Haciendo clic en los checks se irán asignando/eliminando los diferentes roles al usuario.
Si queremos eliminar al usuario basta con pinchar en el icono de la papelera.
Esta pestaña será la que nos permita la creación/edición de los roles de nuestra aplicación, así como ver los usuarios que tiene un determinado rol pudiendo gestionar su pertenencia o no.
En esta pestaña podremos ver una estructura de árbol con todos los roles que dispone nuestra aplicación así como toda la información relativa a cada rol.
Al hacer clic sobre un rol del árbol se nos cargará a la derecha un listado de todos los usuarios que tienen dicho rol, permitiéndonos quitárselo. Adicionalmente hay un check Mostrar todos que permite mostrar todos los usuarios de la aplicación y asignarles el rol seleccionado si no lo tuvieran.
Bajo esa tabla podemos observar otra que nos muestra los objetivos que tiene el rol seleccionado asignados y las acciones que se permiten sobre dichos objetivos.
En esta pestaña podremos definir para cada rol que objetivos tiene y qué acciones podrá realizar sobre dichos objetivos.
Situado a la izquierda tendremos el árbol de roles, igual que en la pestaña anterior, y a la derecha tendremos una tabla que nos permitirá, para el rol seleccionado asignar o eliminar objetivos y acciones.
Para ello pulsaremos el botón Nuevo de dicha tabla y en el desplegable que aparece escribiremos el nombre de la acción a realizar y seleccionaremos en el desplegable los objetivos a los que queremos asignarle esta acción.
En esta pestaña podremos definir los diferentes objetivos/acciones de nuestra aplicación, así como ver qué objetivos están cubiertos por qué roles.
En la tabla de la izquierda podremos ver todos los objetivos junto con su descripción y en la de la derecha las acciones que posee el objetivo seleccionado y los roles que pueden ejecutar dicha acción.
Dándole al botón Nuevo podremos asignar nuevas acciones a los objetivos existentes de igual manera que en el apartado anterior.