Configurar múltiples contextos de seguridad en Spring Security 3.1.
0. Índice de contenidos.
1. Introducción
A partir de la versión 3.1, Spring Security proporciona soporte para la configuración de múltiples contextos de seguridad, cada uno apuntando a su propio manager de autenticación.
En un frontal de aplicación, en una web pública, quizás tengamos la necesidad de securizar un área de clientes y, adicionalmente, proporcionar servicios web del tipo que elijamos (REST por ejemplo) securizados, con otra fuente de autenticación distinta a la del área de clientes. Ambas, dentro de la misma aplicación, empaquetadas dentro del mismo war, por ejemplo:
- http://www.mi-comercio-online.com/: es público,
- http://www.mi-comercio-online.com/clientes/: es privado con autenticación por formulario y usuario y contraseña previo registro,
- http://www.mi-comercio-online.com/ws/rss/: es privado con autenticación básica y un usuario y contraseña genérico o distinto al de registro de usuarios.
En este tutorial vamos a revisar cómo podemos realizar dicha configuración con el soporte de Spring Security.
Se presuponen ciertos conocimientos previos sobre Spring Security, en adictos al trabajo ya hemos publicado varios tutoriales sobre la materia.
2. Entorno.
El tutorial está escrito usando el siguiente entorno:
- Hardware: Portátil MacBook Pro 15′ (2.4 GHz Intel Core i7, 8GB DDR3 SDRAM).
- Sistema Operativo: Mac OS X Lion 10.7.4
- Spring Security 3.1.0.M1.
3. Configuración.
El contenido de nuestro applicationContext-security.xml tendrá un contenido como el que sigue:
<?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:sec="http://www.springframework.org/schema/security" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:context="http://www.springframework.org/schema/context" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/security http://www.springframework.org/schema/security/spring-security.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd"> <!-- REST services security --> <sec:http auto-config="false" authentication-manager-ref="wsAuthenticationManager" use-expressions="true" pattern="/ws/**"> <sec:http-basic /> <sec:intercept-url pattern="/ws/**" access="hasRole('ROLE_ADMINISTRATION')" /> </sec:http> <sec:authentication-manager id="wsAuthenticationManager"> <sec:authentication-provider> <sec:user-service> <sec:user name="${security.front.ws.userName}" password="${security.front.ws.password}" authorities="ROLE_ADMINISTRATION" /> </sec:user-service> </sec:authentication-provider> </sec:authentication-manager> <!-- CUSTOMER zone security --> <sec:http auto-config="false" access-denied-page="/error.xhtml" authentication-manager-ref="customerAuthenticationManager" use-expressions="true"> <sec:intercept-url pattern="/clientes/**" access="hasRole('ROLE_CUSTOMER')" /> <sec:form-login login-page="/acceso" authentication-failure-url="/acceso?error=1" login-processing-url="/acceder" default-target-url="/clientes" always-use-default-target="true" /> <sec:logout invalidate-session="true" logout-url="/salir" logout-success-url="/" /> </sec:http> <sec:authentication-manager id="customerAuthenticationManager"> <sec:authentication-provider > <sec:password-encoder hash="md5" base64="true" > <sec:salt-source system-wide="${password.salt.encoder}" /> </sec:password-encoder> <sec:jdbc-user-service data-source-ref="dataSource" users-by-username-query="select email as username, clave as password, activo as enabled from CLIENTES where email=?" authorities-by-username-query="select email as username, 'ROLE_CUSTOMER' as authorities from CLIENTES where email=?" /> </sec:authentication-provider> </sec:authentication-manager> </beans>
3.1. Configuración de la seguridad del contexto de Web Services.
Debemos destacar:
- línea 12: la ubicación de la configuración de los dos contextos de seguridad (<sec:http) no es casual, debemos configurar primero el menos restrictivo; la configuración de los contextos será secuencial, con lo que el primero debe configurar el área más restringida, en nuestro caso /ws/**, el resto de urls pasará al segundo contexto. Usamos la referencia a un manager de autenticación propio para este contexto,
- línea 14: la configuración de nuestro contexto de seguridad para los web services será basic, mostrará un diálogo del navegador para la petición de usuario y contraseña, esto nos permitirá acceder a los servicios web securizados de forma programática,
- línea 15: la url que intercepta debe tener la misma raíz que el pattern de configuración del contexto de seguridad, línea 12,
- línea 19: hemos configurado un manager de autenticación para el contexto de seguridad que utiliza una configuración simple de usuarios y contraseñas; en concreto un solo usuario cuyo nombre y contraseña se obtiene de un «property place holder configurer» de spring y se asigna manualmente el rol de administrador. Para este ejemplo nos basta, pero podríamos utilizar un manager de autenticación cuan complejo necesitemos.
3.2. Configuración de la seguridad del área de clientes.
Debemos destacar:
- línea 28: usamos la referencia a un manager de autenticación propio para este contexto y no usamos un patrón de capturas de url, con lo que será el contexto de seguridad por defecto, que recibirá las urls que no intercepten los contextos configurados previamente en el fichero,
- línea 31: interceptores de urls con el rol asociado a cada una de ellas,
- línea 34: configuración de la seguridad a través de un login de formulario, y las urls de redirección,
- línea 37: configuración del path de salida o logout,
- línea 42: configuración del manager de autenticación para el área de clientes, en nuestro caso establece las consultas a realizar para recuperar usuario y roles y un nivel de encriptación haciendo uso de un salt fijo, para que las contraseñas encriptadas no sean predecibles y susceptibles de un ataque de diccionario.
4. Referencias.
5. Conclusiones.
Seguimos usando de forma extensiva todos los módulos de Spring para configurar, en este caso y de forma sencilla, la autenticación y autorización de nuestras aplicaciones web.
Cada vez más, las aplicaciones web proporcionan servicios web ligeros, de tipo REST, para permitir la consulta de información o proporcionar otro tipo de interacciones. Con lo visto en este tutorial, podemos proporcionarlos securizados con un nivel de autenticación distinto al de otras áreas de securidad de la aplicación.
Con todo ello, evitamos desplegar dos aplicaciones distintas o reutilizar un manager de autenticación de clientes para un servicio que puede que no se proporcione en exclusiva o solamente para ellos.
Un saludo.
Jose