Enrique Viñé Lerma

Consultor tecnológico de desarrollo de proyectos informáticos.

Ingeniero Técnico en Informática por la Universidad Politécnica de Madrid.

Puedes encontrarme en Autentia: Ofrecemos servicios de soporte a desarrollo, factoría y formación

Somos expertos en Java/J2EE

Ver todos los tutoriales del autor

Fecha de publicación del tutorial: 2008-12-16

Tutorial visitado 36.236 veces Descargar en PDF

Utilización de grupos en Spring Security

0. Índice de contenidos

1. Introducción

En este primer tutorial que realizo en Autentia vamos a ver, con un sencillo ejemplo, como se configura Spring Security para controlar el acceso a los recursos de una aplicación, por medio de la asignación de roles a grupos de usuarios, los cuales se podrán modificar desde una base de datos.

Spring Security es un subproyecto del framework Spring, que permite gestionar completamente la seguridad de nuestras aplicaciones Java, y cuyas ventajas principales son las siguientes:

  • Es capaz de gestionar seguridad en varios niveles: URLs que se solicitan al servidor, acceso a métodos y clases Java, y acceso a instancias concretas de las clases.

  • Permite separar la lógica de nuestras aplicaciones del control de la seguridad, utilizando filtros para las peticiones al servidor de aplicaciones o aspectos para la seguridad en clases y métodos.

  • La configuración de la seguridad es portable de un servidor a otro, ya que se encuentra dentro del WAR o el EAR de nuestras aplicaciones.

  • Soporta muchos modelos de identificación de los usuarios (HTTP BASIC, HTTP Digest, basada en formulario, LDAP, OpenID, JAAS y muchos más). Además podemos ampliar estos mecanismos implementando nuestras propias clases que extiendan el modelo de Spring Security.

2. Herramientas utilizadas

Este tutorial ha sido desarrollado en Windows Vista, y para su elaboración se han utilizado las siguientes herramientas:

3. Creando una aplicación de prueba

Creamos un nuevo proyecto web dinámico. Podemos darle el nombre que queramos, en mi caso lo he llamado “PruebaSeguridad”.

Vamos a seleccionar el Target Runtime pulsando sobre el botón new.




Seleccionamos como servidor Apache Tomcat 6.




Seleccionamos la ruta donde tenemos instalado el tomcat, en mi caso “C:\Program Files\Apache Software Foundation\apache-tomcat-6.0.18”, y pulsamos finalizar.




Vamos a crear tres sencillas páginas jsp de prueba dentro de la carpeta WebContent.

En la primera, “index.jsp”, mostraremos un menú con dos opciones. Cada opción redirigirá a una de las otras dos páginas, a las cuales restringiremos el acceso más adelante por medio de Spring Security.

<%@ page language="java" contentType="text/html; charset=ISO-8859-1"
pageEncoding="ISO-8859-1"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
<title>Inicio</title>
</head>
<body>
<h1>Indice</h1>

<p><a href="villancicos.jsp">Listado de villancicos</a></p>
<p><a href="administracion.jsp">Administracion</a></p>
</body>
</html>

El contenido de las otras dos páginas podría ser cualquiera. En “villancicos.jsp”, ya que se acerca la Navidad, mostraremos una lista con algunos villancicos populares, un enlace para poder volver al índice y otro para salir (y poder volver a identificarnos en la aplicación).

<%@ page language="java" contentType="text/html; charset=ISO-8859-1"
pageEncoding="ISO-8859-1"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">

<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
<title>Listado de villancicos</title>
</head>
<body>
<h1>Listado de villancicos</h1>
<table>
<tr>
<th>Titulo</th>
<th>Popularidad</th>
</tr>
<tr>
<td>Los peces en el río</td>
<td>90</td>
</tr>
<tr>
<td>Campana sobre campana</td>
<td>95</td>
</tr>
<tr>
<td>La marimorena</td>
<td>97</td>
</tr>
</table>

<p><a href="index.jsp">Volver al indice</a></p>
<p><a href="j_spring_security_logout">Salir</a></p>
</body>
</html>

La url “j_spring_security_logout” será capturada por el interceptor de Spring Security una vez que lo hayamos configurado, y permitirá hacer logout al usuario, de forma que si intenta acceder de nuevo a un recurso protegido, se le volverán a solicitar los datos de identificación.

En la página de administración, mostraremos un mensaje, un enlace para volver al índice y otro para salir.

<%@ page language="java" contentType="text/html; charset=ISO-8859-1"
pageEncoding="ISO-8859-1"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">

<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
<title>Administracion</title>
</head>
<body>
<h1>¡Estás en la página de administración!</h1>

<p><a href="index.jsp">Volver al indice</a></p>
<p><a href="j_spring_security_logout">Salir</a></p>
</body>
</html>

Por último, para comprobar que todo funciona correctamente, ejecutamos nuestra pequeña aplicación en el Tomcat y desde un navegador probamos su funcionamiento.







4. Creando una base de datos para gestionar los usuarios, grupos y roles

Creamos un nuevo esquema de base de datos, utilizando una consola del sistema. Deberemos utilizar un usuario con permiso para crear nuevos esquemas en la base de datos.

Para crear el esquema utilizaremos la sentencia: “create schema seguridad;”.




Para crear las tablas hemos utilizado los siguientes scripts.

create table users(
username varchar(50) not null primary key,
password varchar(50) not null,
enabled boolean not null);

create table authorities (
username varchar(50) not null,
authority varchar(50) not null,
constraint fk_authorities_users foreign key(username) references users(username));

create unique index ix_auth_username on authorities (username,authority);

create table groups (
id bigint auto_increment primary key,
group_name varchar(50) not null);

create table group_authorities (
group_id bigint not null,
authority varchar(50) not null,
constraint fk_group_authorities_group foreign key(group_id) references groups(id));

create table group_members (
id bigint auto_increment primary key,
username varchar(50) not null,
group_id bigint not null,
constraint fk_group_members_group foreign key(group_id) references groups(id));

NOTA: para que el servidor pueda encontrar el driver de MySql habrá que añadir el conector (“mysql-connector-java.jar”) a la carpeta de librerías del Tomcat (“%TOMCAT_DIR%\lib”).

5. Configurando Spring para controlar la seguridad de nuestra aplicación

Antes de nada, deberemos añadir dentro de “WebContent/lib” al menos las siguientes librerías, que se incluyen con Spring y Spring Security:




Creamos el fichero de configuración para Spring Security, dentro de la carpeta WEB-INF, al que llamaremos “applicationContext-security.xml”. El esqueleto básico será el siguiente:

<?xml version="1.0" encoding="UTF-8"?>

<beans:beans xmlns="http://www.springframework.org/schema/security"
xmlns:beans="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:p="http://www.springframework.org/schema/p"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.0.xsd
http://www.springframework.org/schema/security http://www.springframework.org/schema/security/spring-security-2.0.1.xsd">

</beans:beans>

Configuramos los interceptores de Spring Security, y establecemos los permisos adecuados para nuestras páginas:

  • La página de índice no tendrá restringido el acceso.

  • La página de administración tendrá el acceso restringido a los usuarios que tengan el rol “ROLE_ADMIN”.

  • El resto de páginas estarán restringidas a usuarios con el rol “ROLE_USER”.

    <http>
<intercept-url pattern="/index.jsp" filters="none" />
<intercept-url pattern="/administracion.jsp" access="ROLE_ADMIN" />
<intercept-url pattern="/*" access="ROLE_USER" />
<form-login />
<anonymous />
<http-basic />
<logout logout-success-url="/index.jsp" />
</http>

Spring Security aplicará la lista de interceptores en el orden en que aparece. Cuando encuentre un patrón adecuado, aplicará los permisos correspondientes y no continuará leyendo el resto de interceptores. Por tanto es importante colocar primero los filtros más específicos y después los más generales.

Además indicamos que nos muestre una página de login y el tipo de autenticación que vamos a utilizar, así como la página a la que se debe redirigir al hacer logout.

A continuación configuramos el AuthenticationProvider, que utilizará como UserService una de las implementaciones que vienen con Spring Security: JdbcDaoImpl. Esta implementación nos permite configurar los permisos de los usuarios en una base de datos a la que se accederá por medio de un DataSource.

    <authentication-provider user-service-ref="userService" />

<beans:bean id="userService" class="org.springframework.security.userdetails.jdbc.JdbcDaoImpl">
<beans:property name="dataSource" ref="seguridadDataSource" />
<beans:property name="enableGroups" value="true" />
</beans:bean>

La propiedad “enableGroups” permite activar el uso de grupos para controlar la seguridad. Es importante cambiar el valor de esta propiedad si queremos utilizar grupos de seguridad, ya que por defecto vale false.

Añadimos el DataSource, indicando el usuario, contraseña y la URL a nuestro esquema de base de datos.

    <beans:bean id="seguridadDataSource" class="org.apache.commons.dbcp.BasicDataSource" destroy-method="close"
p:driverClassName="com.mysql.jdbc.Driver" p:url="jdbc:mysql://localhost:3306/seguridad?autoReconnect=true"
p:username="root" p:password="root"/>

Por último debemos editar la configuración del fichero “web.xml” y añadir las siguientes líneas.

<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>/WEB-INF/applicationContext-security.xml</param-value>
</context-param>

<listener>
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>

<filter>
<filter-name>springSecurityFilterChain</filter-name>
<filter-class>org.springframework.web.filter.DelegatingFilterProxy</filter-class>
</filter>

<filter-mapping>
<filter-name>springSecurityFilterChain</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>

El parámetro de contexto “contextConfigLocation” indica la ruta o rutas de los ficheros de configuración de Spring. En nuestro caso indicamos la ruta del fichero de configuración creado anteriormente.

El ContextLoaderListener se encargará de cargar los ficheros de configuración de Spring indicados en “contextConfigLocation”.

El filtro de seguridad es el encargado de manejar las peticiones que se hagan a todas las URLs para permitir o no el acceso de acuerdo a los permisos que hayamos establecido en el fichero de configuración.

Ahora podemos volver a arrancar nuestro servidor para probar los cambios. Al intentar acceder al listado de villancicos o a la página de administración se nos redirige a una página de login. Todavía no podremos acceder a estas páginas, ya que no hemos creado ningún usuario con los roles adecuados.




6. Añadiendo usuarios, grupos y roles

Ahora que ya está configurada nuestra aplicación de prueba, solamente nos queda añadir los usuarios, grupos y roles a la base de datos.

Añadimos los siguientes usuarios a la tabla USERS:

username   password   enabled
-----------------------------
'enrique' 'enrique' 1
'juan' 'juan' 1
'lucas' 'lucas' 0
'pepe' 'pepe' 1
'rosa' 'rosa' 1

Añadimos los siguientes grupos a la tabla GROUPS:

id   group_name
----------------------
1 'usuarios'
2 'administradores'
3 'invitados'

A continuación podemos dar roles a los grupos, añadiendo los siguientes registros en la tabla GROUP_AUTHORITIES, que relaciona roles con grupos. En nuestro ejemplo hemos añadido un único rol a cada grupo, pero es posible asignar n roles a cada uno. El grupo 'invitados' no tiene ningún rol asignado, por lo que los usuarios que pertenezcan a él no tendrán permisos definidos y no podrán acceder a los recursos protegidos.

group_id   authority
--------------------
1 'ROLE_USER'
2 'ROLE_ADMIN'

Por último, añadimos los usuarios a los grupos, desde la tabla GROUP_MEMBERS, que relaciona grupos con usuarios. Cada usuario podrá pertenecer a varios grupos y sus roles efectivos serán la unión de los roles de cada grupo a los que pertenezca.

id  username   group_id
-----------------------
2 'lucas' 2
3 'juan' 1
4 'rosa' 3
5 'enrique' 2
6 'pepe' 1
8 'enrique' 1

De esta forma los usuarios “juan” y “pepe” pertenecerán al grupo “usuarios”, mientras que “lucas” pertenecerá al de “administradores”. “rosa” pertenece al grupo invitados, que no tiene asignado ningún permiso, mientras que “enrique” pertenece tanto al grupo de administradores como al de usuarios.

Efectivamente, no hemos utilizado la tabla AUTHORITIES para nada. Esta tabla permite asignar roles directamente a los usuarios, pero en nuestro caso hemos preferido realizar esta asignación a través de los grupos. No obstante, todavía podríamos asignar permisos directamente a los usuarios si utilizamos esta tabla, de forma que el usuario tendría la suma de sus permisos más los que tengan los grupos a los que pertenece. Si queremos deshabilitar la asignación de permisos directamente a los usuarios (es decir que no se tenga en cuenta la tabla AUTHORITIES) tendremos que asignar el valor false a la propiedad “enableAuthorities” de nuestro UserService:

<beans:bean id="userService" class="org.springframework.security.userdetails.jdbc.JdbcDaoImpl">
<beans:property name="dataSource" ref="seguridadDataSource" />
<beans:property name="enableGroups" value="true" />
<beans:property name="enableAuthorities" value="false" />
</beans:bean>

La propiedad “enableAuthorities” toma el valor true por defecto, al contrario que “enableGroups”. Es importante dejar al menos una de las dos propiedades (enableGroups o enableAuthorities) a true, ya que de lo contrario obtendremos un error de configuración de Spring Security.

Podemos intentar entrar en la aplicación con los distintos usuarios para ver si obtenemos el comportamiento esperado.

Vemos que cualquiera puede acceder a la página de indice, incluso aunque no se haya identificado, pero cuando pulsamos en uno de los enlaces se nos muestra la página de login.

Cuando probamos a acceder con el usuario “lucas” se nos muestra un mensaje indicando que el usuario está deshabilitado (está en inglés, ya que es un formulario de login que implementado por defecto Spring Security).




Cuando probamos con “rosa” ocurre algo parecido, pero esta vez el mensaje es diferente, ya que el usuario no tiene los permisos adecuados.




Por último podemos comprobar que “juan” y “pepe” pueden acceder solamente al listado de villancicos, pero cuando intentan acceder a la página de administración se muestra el siguiente error, ya que no tienen permiso para acceder a la página.


El único usuario al que se permite acceder a la página de administración es “enrique”, ya que lo hemos añadido al grupo de administradores.

7. Conclusiones

A la vista de los resultados de este tutorial podemos sacar las siguientes conclusiones:

  • Spring Security nos ofrece servicios de identificación y acceso a los recursos de nuestras aplicaciones de una forma potente y sencilla, sin tener que escribir ni una sola línea de código.

  • Podemos asignar los permisos directamente a los usuarios o a grupos de usuarios, o incluso mezclar ambas formas.

  • Podemos añadir fácilmente seguridad en nuestras aplicaciones existentes o modificar la seguridad de una aplicación rápidamente, ya que Spring Security separa claramente la seguridad de una aplicación de su lógica.

Y eso es todo. Desde autentia esperamos que este tutorial os haya sido de utilidad y os ayude a gestionar la seguridad de vuestras aplicaciones mediante Spring Security.

A continuación puedes evaluarlo:

Regístrate para evaluarlo

Por favor, vota +1 o compártelo si te pareció interesante

Share |
Anímate y coméntanos lo que pienses sobre este TUTORIAL:

Fecha publicación: 2014-08-11-16:18:57

Autor: jedaro

Hola enrique, buen tuto. Pero me esta saliendo un error en el xml al declarar los interceptores <http></http> justo al inicio de la primera etiqueta:The markup in the document following the root element must be well-formed. A que se debe, lo copie tal cual como aparece en el tuto

Fecha publicación: 2013-03-05-12:05:00

Autor: gisgert

Hola, muy bueno el tutorial, pero tengo un problema. No consigo recuperar despues del login los datos del usuario, nada mas acceder lo intento desde una clase @Controller con String usuario = req.getParameter("j_username");. Lo que quiero es a traves del usuario que se ha logado identificar a que cliente pertenece, almacenarlo en un objeto session y utilizarlos posteriormente para querys. Muchas gracias

Fecha publicación: 2012-01-20-16:19:48

Autor: evlerma

Si vas a usar Spring Security, puedes seguir este tutorial, independientemente del IDE que utilices (Netbeans, Eclipse, bloc de notas...). Espero haber resuelto tu duda.
Saludos.

Fecha publicación: 2012-01-20-15:17:38

Autor: pablosfar2011

hola soy Pablo de Argentina y quería saber como puedo desarrollar este mismo sistema de autenticación de miembros y roles, pero usando Netbeans 6.9.1, este sistema se llama Membership en Asp.Net y me gusto mucho su uso, lo que quiero ahora es hacerlo pero en Java por Netbeans, si alguien me puede ayudar se lo agradeceria

Fecha publicación: 2011-04-19-15:57:25

Autor: evlerma

Hola jaider2523.
En realidad al ejemplo le faltan muchas cosas para poder ser una aplicación real, pero se trata precisamente de eso, de un ejemplo sencillo que muestra cómo se pueden utilizar grupos en Spring Security. El código no está disponible, pero todas las clases y configuración necesarias están explicadas detalladamente en el tutorial. No se necesita nada más para que funcione este ejemplo; si no me crees, compruébalo tú mismo.
En este ejemplo se usa "org.springframework.security.userdetails.jdbc.JdbcDaoImpl", por tanto no necesitamos definir un UserDetailService personalizado.
Saludos.

Fecha publicación: 2011-04-19-14:57:50

Autor: jaider2523

Donde se pueden descargar los ejemplos?, porque en realidad a este ejemplo le hace falta una gran parte del mvc, las clases y su configuracion para que pueda ser reconocido el userdetail...

Fecha publicación: 2011-02-06-12:04:08

Autor: jcarmonaloeches

Muchas gracias Enrique, muy bien explicado.

Fecha publicación: 2010-12-27-14:05:57

Autor: rubenbar02

Buenas, este tutorial esta muy bueno, yo genere spring security en un proyecto de spring roo, pero no puedo cambiar la vista del login que me sale, ya intente cambiar el login.jspx que genera roo, pero no toma los cambios, tenes algun tipo de solucion? gracias.

Fecha publicación: 2010-12-27-13:39:06

Autor: rubenbar02

Buenas, este tutorial esta muy bueno, yo genere spring security en un proyecto de spring roo, pero no puedo cambiar la vista del login que me sale, ya intente cambiar el login.jspx que genera roo, pero no toma los cambios, tenes algun tipo de solucion? gracias.

Fecha publicación: 2009-09-17-01:11:17

Autor:

[LuigiBuilder] He revisado el tutorial y me parece bastante instructivo solo que para la version de Spring 2.5, en el datasource seria asi: &lt;beans:bean id="seguridadDataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource" destroy-method="close" p:driverClassName="com.mysql.jdbc.Driver" p:url="jdbc:mysql://localhost:3306/seguridad?autoReconnect=true" p:username="XXXXXXXXX" p:password="XXXXXXXXX"/&gt; Saludos

Fecha publicación: 2009-05-27-03:46:31

Autor:

[angeles] En el fichero applicationContext-security.xml sobra en el tercera linea &lt;/beans:beans&gt;

Fecha publicación: 2009-04-02-10:23:59

Autor:

[sam] Otro detalle sobre el ejemplo, cuando no se tienen los permisos, te lanza un error:: Estado HTTP 403 - Access is denied -------------------------------------------------------------------------------- type Informe de estado mensaje Access is denied descripci�n El acceso al recurso especificado (Access is denied) ha sido prohibido. -------------------------------------------------------------------------------- Apache Tomcat/6.0.18 ------------------ ¿como se podria que allí fuera a una pagina que tenga un boton o enlace para redirigir a otro lugar? saludos

Fecha publicación: 2009-04-02-09:59:07

Autor:

[sam] Hola adictos al trabajo. Estaba revisando el tutorial sobre utilizació de grupos en Spring Security, muy interesante. Me quedó la duda sobre este comentario::: "Cuando probamos a acceder con el usuario “lucas” se nos muestra un mensaje indicando que el usuario está deshabilitado (está en inglés, ya que es un formulario de login que implementado por defecto Spring Security)." Queria preguntar ¿hay forma de ver ese formulario en español o convertirlo facilmente a español? Esto para tener los mensajes en mi idioma. Agradezco me comenten la posibilidad de transformar el formulario al español y me den luces sobre la manera de hacerlo y/o palabras claves para buscar la forma de hacerlo. Saludos.