Buscar
Social
Ofertas laborales ES
miércoles
may142008

Controlando perfiles de usuario con Struts

La información que hay por Internet referente al tema es escueta y aunque se encuentran muchos artículos al final todos tienen un enlace a alguno de los dos siguientes, que son los únicos interesantes. Por supuesto, como no podría ser de otra manera, en inglés:

www.onjava.com/pub/a/onjava/2004/02/18/strutssecurity.html?page=last&x-order=date

www-128.ibm.com/developerworks/web/library/wa-appsec/?ca=dgr-
lnxw16ServletsTaglibsStrutsSecurity#listing2

Los dos los artículos lo primero que hacen es decir que struts no es una tecnología que lo haga todo, sino que pretende ser una plataforma básica abierta que sirva de base. Después te sueltan el royo de que en una aplicación que se precie se han de contemplar multitud de usuarios con diferentes roles y blablabla… y por fin pasan a dar la solución, que es similar.

Mi solución:

No me voy a poner a traducir ninguno de los artículos, sino que os voy a contar la solución que estoy adoptando, que no es que sea una cosa novedosa, es la misma que la de los artículos, sólo que explicada por mí (de hecho la solución no es mía, sino que es la que hemos adoptado en un proyecto que estoy realizando con más personas).

Consideraciones iniciales:

Lo primero que tenemos que tener en cuenta es que necesitamos un modo de identificación de usuarios en el sistema (login, password). Por este motivo supondremos para la realización de las restricciones que la identificación se ha realizado y que en session tenemos un objeto usuario (que será un registro – u objeto que represente dicho registro – de la tabla usuarios a la que haremos referencia posteriormente).

Como a priori no hemos definido ni los diferentes roles que tendrán los usuarios de la aplicación, ni las secciones en las que se dividirá nuestra aplicación ni los diferentes tipos de acceso que tendremos; y además, lo ideal sería que en caso de tener que modificar alguna de estas cosas fuera lo más rápido posible, la solución que vamos a ver consiste en tener una base de datos (o una serie de tablas dentro de la base de datos que usemos en la aplicación, si usamos alguna) donde almacenaremos toda esta información.

Además tendremos dos niveles de restricción, área de acceso (si el usuario puede o no acceder a la página) y tipo de operación (qué operaciones puede realizar el usuario de las disponibles en la página). Por ejemplo, si tenemos una página con una serie de datos editables habrá usuarios que no puedan acceder a ella, los habrá que puedan acceder pero no cambiar los datos (modo lectura) y los habrá que puedan acceder y cambiar los datos (modo lectura/escritura).

Requisitos de información:

Vamos a ver las tablas que necesitamos incluir en la base de datos y para qué sirve cada una. Evidentemente, dependiendo de los tipos de usuarios que se vallan a tener en la aplicación puede que tengamos que meter alguna tabla más o quitar alguna porque no sea necesaria; pero más o menos será de una forma parecida a esta.

- Usuarios

Entidad que recogerá los datos de los usuarios de la aplicación. En ella guardamos los datos personales de los usuarios, el identificador y la contraseña, y asociamos al usuario un perfil, que será el que defina los permisos.

Atributo Tipo BBDD Comentario
idUsuario (PK) numérico not null Código del usuario
login (UK) texto not null Login en la aplicación
password texto Null Contraseña del usuario
nombre texto Null Nombre del usuario
apellido texto Null Apellidos del usuario
... Null Resto de datos personales...
idPerfil (FK) numérico not null Id del Perfil que define los permisos del usuario.


PK: clave primaria UK: clave única FK: clave ajena

- Perfiles

Entidad que recogerá los perfiles de uso de la aplicación. Realmente la tabla es poca cosa, pero nos da un idPerfil que será el que usemos en los distintos permisos.

Atributo Tipo BD Comentario
idPerfil (PK) numérico not null Código del perfil
perfil texto not null Nombre del perfil


- Tipo de acceso

Entidad que recogerá los tipos de acceso, que pueden ser de creación, edición, eliminación, consulta...

Atributo Tipo BBDD Comentario
idTipoAcceso (PK) numérico not null Código del tipo de Acceso
codigo Numérico not null Código constante para identificar el tipo de acceso
tipoAcceso texto not null Descripción del tipo de acceso


- Secciones de la aplicación

Entidad que recogerá las distintas secciones de la aplicación sobre las que queremos definir permisos de acceso. Por ejemplo en una aplicación para una tienda podemos tener una zona de para el almacén, otra para los trabajadores de la tienda y otra para los clientes.

Atributo Tipo BBDD Comentario
idSeccionAplicacion (PK) numérico not null Código de la Sección de la Aplicación
codigo texto not null Código constante para identificar la sección
seccionAplicacion texto not null Descripción de la sección


- Permisos

Entidad que recogerá los permisos que los distintos perfiles tienen sobre las diferentes secciones. En esta tabla es donde asociamos el perfil con una sección de la aplicación y lo dotamos de una serie de permisos.

Atributo Tipo BBDD Comentario
idPermiso (PK) numérico not null Código del permiso
idTipoAcceso(FK) numérico not null Código del tipo de acceso
idSeccionAplicacion(FK) numérico not null Código de la sección de la aplicación
idPerfil(FK) numérico not null Código del perfil


Implementación de las restricciones sobre el sistema

Anteriormente hemos dicho que hay dos tipos de restricción, de acceso y de operación. Es ahora cuando realizaremos una diferenciación entre ellas, a la hora de implementarlas.

- Restricción de acceso

Pasando ya al lenguaje de struts, podemos entender una restricción de acceso como la posibilidad del usuario en cuestión de ver o no el resultado de un determinado Action, ya que se supone que antes de ver una página determinada se habrá de ejecutar el correspondiente Action, que es el que genera los datos a mostrar en la página.

Lo que queremos entonces es que si un usuario tiene permisos se ejecute el Action y se pase a la página jsp correspondiente; o que en el caso de no tener permisos pasemos a una página de error. Lo vamos a realizar en tres pasos:

1-. Superclase para los Action

Partiendo de que tenemos varias secciones en la aplicación y que cada sección se encuentra implementada por un conjunto de Actino, vamos a colocar sobre los Action de cada sección una superclase que en su método execute lo primero que compruebe sean los permisos de acceso del usuario. Sería una cosa más o menos así:

public abstract class RestriccionAction extends Action    
{

public ActionForward execute(.....)
{
doRestriccion(…);
return _execute(…);
}

public abstract ActionForward _execute(….);

private void doRestriccion(……) throws AccesoNoPermitidoException
{
/* Este metodo realiza las comprobaciones de acceso con
el perfil del usuario que haya en sesión */

}

}


De tal forma que los Action de la sección heredarán de este y será de la forma:

public class CuarquierCosaAction extends RestriccionAction    
{
public ActionForward _execute(.....)
{
/* Este es el método execute que tenía el Action, pero le cambiamos el nombre
para que se ejecute el de la clase padre que implementa la restricción */

}
}


2-. Extender ActionMapping

Extenderemos la clase ActionMapping de struts para darle más atributos, ya que interesará tener para cada Action datos relativos a la sección a la que pertenece, así que le añadiremos el atributo applicationZone.

public class SecurityActionMapping extends ActionMapping    
{
private String zone = null;

public String getApplicationZone()
{
return zone;
}

public void setApplicationZone(String newZone)
{
zone = newZone;
}
}


A partir de ahora, el parámetro de tipo ActionMapping del método execute de los Action será de tipo SecurityActionMapping (podremos hacer un casting dentro del método a un objeto de esta clase con el objeto de entrada). Pero para hacer que esto sea así, antes hemos de completar el siguiente paso.

3-. Inclusión del atributo en el struts-config.xml

En el fichero struts-config.xml modificamos las definiciones de los objetos Action incluyendo el atributo className=”ruta_de_paquetes.SecurityActionMapping” y una directiva set-property. De la siguiente forma

 path=”...” 
[...]
className="ruta_de_paquetes.SecurityActionMapping"
[...] >

property="applicationZone"
value="CODIGO_DE_SECCION" />

[...] />
>



El código de sección deberá coincidir el valor del atributo codigo de algún registro de la base de datos de la tabla de secciones de la aplicación.

- Restricción de operación

Ya hemos dicho que larestricción de operación se puede entender cómo la necesidad de un determinado perfil para disponer de determinadas opciones o controles en laspáginas JSP que se visualizan, como pueden ser permisos de edición o no de algunos datos. (por supuesto, si un usuario tiene restringido el botón editar – por poner un ejemplo – de una página jsp, también deberá tener restringida la ejecución del Action que realiza la edición, mediante una restricción de acceso)

Las restricciones de operación deberán tener reflejo en las páginas JSP que muestran la información y los controles para operar sobre ella; por ejemplo, si no se pueden editar los datos, los campos de edición deberán aparecer en sólo lectura y el botón de grabar debe estar oculto. Lo haremos en dos pasos:

1-. Colocación de permisos de operación en request

En el Action que implementa la restricción de acceso correspondiente se establecerán en ámbito de request los permisos de operación que el usuario que hay en session tiene en la sección del Action que se invocó para llegar hasta el JSP. Los permisos posibles dependerán realmente de cómo sea nuestra aplicación y de, por supuesto, los permisos que tenga el perfil del usuario.

Por ejemplo: Si el usuario tiene permisos para modificar datos, se ha de establecer en ámbito de request el atributo canEdit a true

request.setAttribute(“canEdit”, new Bolean(true));

2-. Restricción en las páginas JSP

En las páginas JSP se han de restringir la aparición o la funcionalidad de los diferentes controles dependiendo de los permisos que tengamos establecidos en request. Por ejemplo, si tenemos canEdit el botón de edición deberá aparecer y los campos ser editables; pero si no tenemos canDelete, el botón de borrar deberá permanecer oculto (por supuesto el usuario no podrá tener acceso al Action que realiza dicho borrado – mediante una restricción de acceso).

Anexo: De la excepción AccesoNoPermitidoException a la pantalla de error

Antes hemos usado la excepción AccesoNoPermitidoException, que sería de la forma:

public class AccesoNoPermitidoException extends Exception    
{
public void printStackTrace()
{
super.printStackTrace();
}
}


Esto lo que provoca es un fallo en la llamada al servidor, por lo que se devuelve la típica página de error. Evidentemente queremos que la página que se muestre sea distinta, una del estilo “no tiene permisos para realizar la acción solicitada. Contacte con el administrador...”. Además, de camino vamos a tener la posibilidad de tener nuestra propia página de error para la aplicación.

¿Cómo lo haremos? De una forma fácil: vamos a crear un manejador de excepciones, lo vamos a poner como manejador de excepciones de la aplicación y vamos a crear nuestra página de error y nuestra página de acceso no permitido.

El manejador de errores va a ser una clase del estilo:

public class ExceptionHandler extends ExceptionHandler    
{
public ActionForward execute(Exception exception, ExceptionConfig config,
ActionMapping mapping, ActionForm form, HttpServletRequest request,
HttpServletResponse response) throws ServletException
{
if(exception.getClass().equals(AccesoNoPermitidoException.class))
{
return mapping.findForward("permisoDenegado");
}
else
{
request.setAttribute("exception",exception);
return mapping.findForward("error");
}
}
}


El método lo que ha de hacer es redireccionar al correspondiente forward (que posteriormente incluiremos en el struts-config.xml). Como queremos diferenciar entre un acceso no permitido y una excepción, según lo que sea (usando la condición if(exception.getClass().equals(AccesoNoPermitidoException.class)) vemos si es un acceso no permitido) redireccionamos a un sitio o a otro. Además, si es una excepción metemos en request dicha excepción, por si luego la queremos mostrar en la pantalla de error.

Para establecer nuestro manejador de excepciones como manejador por defecto incluimos en el struts-config.xml el siguiente código detrás de la sección form-beans:

>
key="lang.exception" type="java.lang.Exception"
handler="ruta_de_paquetes.ExceptionHandler" />

>



Y para los forwards de error y acceso no permitido incluimos lo siguiente a continuación:

>
name="error" path="/error.jsp" contextRelative="true" />
name="permisoDenegado" path="/permisoDenegado.jsp" contextRelative="true" />
>



Por último tenemos que crear las páginas error.jsp y permisoDenegado.jsp

Bueno, pues hemos llegado al final...
martes
may132008

Primeros resultados del Android Developer Challenge

Hace ya unos meses desde que Google anuncio su incursión en el campo de la telefonía móvil anunciando la disponibilidad de una nueva plataforma llamada Android, la cual está basada en Java y  contiene un sistema operativo con diferentes APIs.

Para incentivar el interés en el SO y obtener aplicaciones para Android, Google lanzó un concurso con suculentos premios y los 50 ganadores de la primera ronda ya están aquí después de la deliberación que han llevado a cabo 100 jueces. Según el blog oficial de Android, muchos de las aplicaciones contienen un factor social, que por otra parte parece bastante lógico tal y como están las cosas en la red últimamente. Los 50 ganadores van a obtener 25.000 dolares de premio y van a pasar a la siguiente ronda donde les esperan más premios y la satisfacción de llegar a la final, ya que quedar dentro de los 50 primeros de 1,788 posibles no debe ser nada fácil.

En la lista hay un nombre que parece hispano, esperemos que sea un usuario de javahispano (aplicación BioWallet - Jose Luis Huertas Fernandez)
martes
may132008

Netbeans vs Eclipse en el mundo hispano: una encuesta con 3400 participantes

Desde javaHispano estamos llevando a cabo una extensa encuesta, con 3400 participantes hasta la fecha, para determinar el porcentaje de desarrolladores Java hispanos que prefieren Netbeans y los que prefieren Eclipse. Muchos de vosotros habéis participado en la encuesta y... tan siquiera sois conscientes de ello ;).

 

Supongo que a estas alturas todos conocéis la JavaCup, el torneo de fútbol virtual Java que coorganizamos la revista Sólo Programadores, Sun Microsystems Ibérica y javaHispano. El software para participar en el concurso se distribuye empaquetado como un proyecto para Netbeans y como un proyecto para Eclipse. Por el resto, el software es idéntico. Es decisión personal del participante si quiere usar Netbeans o Eclipse en el concurso.

 

El resultado de esta "encuesta" encubierta es el siguiente: con 3389 descargas efectuadas hasta la fecha, 1881 han preferido Eclipse y 1508 Netbeans. Netbeans, por tanto, ha sido preferido por el 44.5% de los usuarios y Eclipse por el 55.5%.

Puede que sea un modo un tanto particular de hacer una encuesta, pero hasta donde yo conozco ésta es la encuesta más fiable sobre el uso de Netbeans y Eclipse entre la comunidad hispana. ¿Qué os parecen los resultados?

martes
may132008

Excelente librería matemática para Java

Michael Thomas Flanagan, profesor de una universidad del Reino Unido, lleva varios años desarrollando en colaboración con sus alumnos una librería científica para Java. La librería es muy completa: cuenta con funcionalidad para realizar operaciones con matrices, estadísticas, generación de números aleatorios, propagación de errores, regresión, optimización, transformadas de Fourier, integrales, interpolaciones, buscar raíces, operaciones con números complejos... y un largo etcétera.

 

Es la mejor librería científica/matemática que yo conozco para Java, o al menos la que más funcionalidad tiene. Tengo experiencia usando sobre todo la parte de transformadas de Fourier, y es la única librería (que no snipet de código) que he encontrado en Java que realice esta función. Java nunca ha sido un bastión fuerte para el cálculo numérico.

 

Sus puntos débiles son que ha sido desarrollada por científicos, que no por ingenieros de software. El API no está bien diseñada y no emplea convenios Java; la documentación de la librería la han hecho "a mano" sin usar el Javadoc. A menudo resulta necesario hackear la librería para conseguir lo que uno quiere; por ejemplo, ellos proporcionan funcionalidad para representar gráficamente una transformada de Fourier. Pero no proporcionan un widget, sino que lanza un Frame (tan siquiera JFrame) nuevo para representarla.

 

El otro punto débil es que la licencia no está demasiado clara. Lo único que te vienen a decir es que puedes usarla gratis en proyectos no comerciales. Pero el código no tiene una licencia propiamente dicha. En cualquier caso, como ya he dicho, para mí es la mejor librería científica que hay en Java.

 

¿Que otras librerías científicas conocéis?

lunes
may122008

Documentación de proyectos

Hacer un proyecto puede ser divertido, entretenido o ameno para un programador. Pero documentarlo ya es harina de otro costal.
Muchas veces la documentación se hace tarde, mal y nunca.
Para ayudar un poco a hacer la documentación he encontrado un post en Linux.com que trata sobre usar un wiki para documentar un proyecto Open Source Using a wiki for FOSS application documentation.
En concreto se han decidido por dokuwiki y algún plugin que tiene.

Actualmente también estoy haciendo un proyecto open source, pero lo que me falta es documentación.
Así que hace unas semanas también me decidí por usar un wiki para documentarlo.
Lo de usar un wiki es fue porque:

  • Lo tendré todo más organizado que usando ficheros de OpenOffice/Word
  • También sirve como documentación para la web
  • Es más facil que escribir html a pelo (Lo intenté y casi muero en el intento)
  • Facilidad para escribir código fuente
  • Quería aprender a usar un wiki

Y también me he decidido por dokuwiki.
La principal característica que yo le veo a dokuwiki es su sencillez de uso e instalación.
El proveedor de mi hosting usa apache+php y no puedo lanzar ningún script en su máquina. Así que necesitaba un wiki que fuera fácil de instalar y en php.
La instalación de dokuwiki es tan sencilla como copiar todos los archivos en un directorio de apache.

Otra de las opciones en las que pensé para documentar el proyecto fue usar OpenBook pero creo que es matar moscas a cañonazos. Y usar OpenOffice/Word me parecía demasiado rudimentario.

¿Que herramientas usáis vosotros para hacer la documentación?

Saludos