Capítulo 6: Spring Security

Anuncio
Capítulo 6:
Spring Security
Cómo hacer de nuestra aplicación un lugar
seguro
Este capítulo se centrará en la seguridad y cómo Spring
a través de su proyecto Spring Security se hace cargo de
ella.
Javier Sevilla Sánchez
Trabajo de fin de carrera de la Ingeniería Técnica en
Informática de Gestión (I.T.I.G)
Contenido
¿Qué es Spring Security? ............................................................................................................... 4
Autenticación en Spring Security .................................................................................................. 4
AuthenticationManager ................................................................................................................ 5
Seguridad en aplicaciones Web .................................................................................................... 7
Autorización en Spring Security .................................................................................................. 10
Seguridad de la capa de servicio ................................................................................................. 12
Configuración de seguridad a nivel global (namespace)......................................................... 12
Seguridad a nivel de bean ....................................................................................................... 12
Con el objeto MethodSecurityInterceptor .............................................................................. 12
Seguridad a nivel de anotación ............................................................................................... 13
¿Qué es Spring Security?
Spring Security se ha convertido en la librería de referencia dentro del mundo Java, para dar
soporte a los servicios de autenticación y autorización de una aplicación. Esto se debe
principalmente a que es un proyecto proyecto enmarcado dentro de Spring y como ya hemos
visto gracias a Spring podremos hacer código mantenible, reutilizable, ágil y robusto. El código
y diseño del componente es inmejorable, es sabido que dentro de la comunidad de
desarrolladores Java tiene un gran uso siendo un referente. Spring Security es un framework
maduro que viene de otro proyecto llamado Acegi. Como la mayoría del framework de Spring,
Spring Security ofrece una gran facilidad de configuración y parametrización, gracias al uso de
mamespace y la inyección de dependencia. Permite la integración con los sistemas legacy de
autenticación más importantes del mercado: BBDD, LDAP, CAS (para single sign-on), gestión de
certificados, etc. Spring Security tiene un gran respaldo de la comunidad con lo que hay una
gran cantidad de documentación y ejemplos.
Autenticación en Spring Security
Un proceso de autenticación consiste en identificar la entidad que realiza una acción sobre la
aplicación y garantizar que es quién dice ser. La entidad que realiza una acción sobre la
aplicación es conocida como principal, en Spring es llamada AuthenticationManager,
encargado de implementar el proceso de autenticación en las aplicaciones.
Antes de describir cómo es el diseño de AutenticationManager, vamos a presentar otros
componentes importantes y necesarios para poder comprender el proceso de autenticación.
Authenticacion, este objeto guardará los datos asociados a AutenticationManager y sus roles.
Así este objeto es en el que sea apoya el AuthenticationManager para implementar el servicio
de autenticación.
SecurityContextHolder, encargado de guardar los datos del principal y sus roles dentro del
contexto de seguridad. Como hemos dicho, la información del principal la alberga
Authentication, así que SecurityContextHolder guarda el objeto Authentication en el contexto
de seguridad. Así la información que reside en el objeto Authentication pueda ser consultada
en todo momento por cualquier componente dentro de la aplicación.
Objeto UserDetailsService, Spring suele delegar responsabilidades en otros objetos, en este
caso el objeto AuthenticationManger delega en el objeto UserDetails las labores de obtención
de la información del usuario sobre el repositorio de seguridad. Así, si los usuarios están en
una base de datos, el objeto UserDetails realizará las consultas necesarias para obtener la
información del AuthenticationManager.
AuthenticationManager
Este interfaz sólo define un método:
Authentication authenticate (Authentication authenticaction) throws AuthenticationException;
El parámetro de entrada tendrá los datos básicos de autenticación. Con este dato se prodecerá
a obtener toda la información de credenciales asociadas con el principal y se comprobará si
dichas credenciales son correctas. En el caso de que las credenciales no sean correctas el
proceso de autenticación lanzará una AuthenticationException. Si la autenticación es correcta
se obtendrán las autoridades asociadas al usuario y serán guardadas en el objeto
Authentication, el cual será devuelto por el método. Éste objeto será guardado por el
componente SecurityContextHolder en el contexto de seguridad.
Como hemos dicho, AuthenticationManager delega responsabilidades, teniendo un conjunto
de componentes ProviderManager los cuales son los encargados de implementar el proceso de
autenticación. Los objetos ProviderManer están más cercanos a la tecnología usada para
impementar el repositorio de seguridad de la aplicación. Así si disponemos de un LDAP,
tendremos el objetoLdapAuthenticationProvider, si accedemos a una base de datos tendremos
un DaoAuthenticationProvider, etc, etc.
En el siguiente diagrama se muestra la colaboración entre componentes para implementar el
proceso de autenticación de la aplicación, en este caso se muestra para un delegado que
buscará en una base de datos gracias al DaoAuthenticationProvider.
Spring tiene un gran número de Providers así, podremos dar soporte a multitud de sistemas.
Así podremos adaptar nuestras aplicaciones a distintas particularidades, presentes y futuras.
Una de las grandes ventajas que tiene Spring Security es la inclusión de namespace específicos
que da sopote a la configuración de los distintos componentes que forman parte de la solución
de autenticación y autorización de aplicaciones. Antes, era necesario definir un conjunto de
beans muy extenso y existía la posibilidad de error en la gestión de las dependencias de los
distintos beans. Gracias a la incorporación de namespace, al desarrollar se abstrae de muchas
particularidades internas de la solución, proporcionando un fichero XML de configuración más
sencillo.
--TODO--CODIGO NAMESPACE
---FIN TODO---Como vemos en el ejemplo el único parámetro de configuración necesario es el gestor de
autenticación donde está el esquema de base de datos donde reside el repositorio de
seguridad.
Este fichero permitirá la configuración de todos los elementos necesarios para realizar la
autenticación y autorización de una aplicación web sobre HTTP.
Seguridad en aplicaciones Web
Lo primero es definir es el ServletFilter DelegatingFilterProxy. Este filtro lo que hace es un
proxy entre los Servlets y el contexto de Spring. Así, este filtro permite que todos los
componentes que forman parte de la arquitectura de Spring Security puedan ser definidos
mediante los ficheros XML.
Spring Security, como ya hemos dicho, se puede configurar mediante el uso de namespace,
que es un fichero XML que cumple un determinado esquema, facilitando la configuración.
Dentro del fichero de configuración incluiremos el siguiente código:
---TODO----
---FIN TODO----
Dentro de la configuración se puede ver como se pueden securizar URL. La etiqueta contiene el
patrón de URL que se quiere securizar y una lista de roles que son necesarios para poder
acceder al recurso, en el caso que se indiquen varios roles, con que se tenga uno de los roles
será suficiente para disponer de permiso para dicha URL.
Dentro de este fichero de configuración se puede configurar las siguientes grandes
funcionalidades:
Remember-me, así el usuarios puede guardar las credenciales en el navegador y así no tener
que volver a introducirlas en el siguiente proceso de autenticación. Usa un soporte de cookies
con aplicación de algoritmos hash para guardar la información.
Selección de canal de seguridad, si usamos el atributo requires-channel dentro de la etiqueta,
se puede exigir que determinadas URL sean seguras dentro de la aplicación. Spring Security
hace las oportunas redirecciones que sean necesarias para el cambio de canal.
Gestión de la sesión, control de timeouts de sesión, y control de la sesión concurrente. El
control de los timeouts de sesión sirve para indicar cuando esta invalidada. El control de sesión
concurrente es para controlar el número de sesiones que están activas para un mismo usuario.
Esto supone una protección contra el ataque de fijación de sesión. ---TODO--http://en.wikipedia.org/wiki/Session_fixation ---END TODO--Soporte para OpenId. ---TODO BUSCAR OPENID---
Spring Security mantiene una cadena de filtros que cada uno de ellos da cabida a una
funcionalidad dentro de los procesos de autenticación y autorización entre cada petición y
respuesta. Es posible modificar la cadena de filtros.
Dentro de estos filtros destacan:
FilterSecurityInterceeptor, el cual es encargado de manejar la seguridad de los recursos HTTP
manejando los elementos definidos en el namespace.
ExceptionTranslationFilter, encargado de manejar excepciones lanzadas por los interceptores
de seguridad y proveer la respuesta HTTP correspondiente.
SecurityContextPersistenceFilter, responsable de guardar el contexto de seguridad entre
peticiones. Básicamente el contexto de seguridad es guardado a nivel de sesión.
Como vemos en la figura, existen numerosos interceptores en la cadena. Toda la cadena de
filtros es creada y aislada del programador mediante el uso de namespace. Sin embargo, es
posible modificar y extender la cadena de filtros.
Autorización en Spring Security
El siguiente diagrama de clases define la arquitectura del módulo de autorización en Spring
Security:
En el centro del diagrama tenemos la clase abstracta AbstractSecurityInterceptor, ésta
representa las capacidades de autorización básicas. Se pueden securizar peticiones HTTP
gracias
a
FilterSecurityInterceptor
e
invocaciones
a
métodos
gracias
a
MethodSecurityInterceptor y AspectJSecurityInterceptor.
Este interceptor delega en el interfaz AccesDecisionManager la decisión de la autorización
final. Este interfaz implementa un método decide que básicamente lo que hace es recibir un
objeto Authentication representando al principal que accede a la petición, un objeto seguro
(url o método) y una lista de aributos con metadatos de seguridad (la lista de roles para los que
se les puede dar acceso).
El siguiente diseño es el definido para el componente AccesDecisionManager:
El diagrama representa el sistema de autorización de Spring Security. Este sistema está basado
en un sistema de votos. Spring Security tiene tres implementaciones de
AccessDecissionManager:
AffirmativeBased, en el caso de recibir un único voto positivo, se le da acceso al recurso. Se
permite controlar el comportamiento en el caso que todos los votos son de abstención.
ConsensusBased, en este caso será necesario que haya más votos positivos que negativos para
dar acceso al recurso protegido. También se puede controlar el comportamiento si todos los
votos son abstención.
UnanimousBased, en este caso será necesario que todos los votos sean positivos para dar
acceso al recurso. Se permite controlar el comportamiento en el caso que todos los votos son
de abstención.
Los objetos AccessDecissionManager hacen uso de AccessDecissionVoter, actualmente Spring
proporciona dos clases de este objeto:
RoleVoter, comprueba cada rol que protege el recurso comprobándolo con el principal que
realiza la petición. Si se tiene uno de los roles devolverá un AffirmativeBased
AccessDecissionManger, así con uno bastará para dar acceso.
AuthenticatedVoter, Este componente permite diferenciar entre acceso anónimo,
completamente autenticado o autenticado mediante remember-me. Así podrá acceder a
páginas que necesitan tener un comportamiento diferente para usuarios autenticados de los
que no.
Todos los componentes del módulo de autorización de Spring Security permiten ser
extendidos para proveer mecanismos de autorización específicos o más profundos.
Seguridad de la capa de servicio
Spring Security permite securizar invocaciones a métodos, comúnmente llamado seguridad a
nivel de capa de servicio. Esto permitirá que tengamos mecanismos de autorización de
invocaciones de componentes de la capa de servicio aportando mayor seguridad.
Spring otorga cuatro configuraciones para la seguridad en la capa de servicio, configuración a
nivel global mediante namespace, mediante el componente MethdoSecurityInterceptor,
basada en anotaciones o a nivel de bean.
En Spring podemos observar cuatro maneras de securizar las ejecuciones de métodos dentro
de Spring Security, Configuración de seguridad a nivel global usando namespace, a nivel de
bean, usando el componente MethodSecurityInterceptor y basada en anotaciones.
Configuración de seguridad a nivel global (namespace)
Spring Security permite una configuración de seguridad a nivel global, esta opción es una
securización centralizada de todos los métodos de la capa de servicio. Adicionalmente,
presenta una expresión AspectJ de definición del pointcut, el cual permite aplicar de manera
flexible seguridad a varios objetos. En el ejemplo expuesto se están securizando todos los
métodos del paquete ---TODO--- com.mycompany ---END TODO--- que acaben por service e
independientemente del número de parámetros que tenga el método.
Seguridad a nivel de bean
Con el objeto MethodSecurityInterceptor
Seguridad a nivel de anotación
Descargar