Você está na página 1de 14

Spring Security 3.

0
Spring Security se ha convertido en la librera de referencia dentro del mundo Java, para dar soporte a los servicios de autenticacin y autorizacin de una aplicacin. Las razones del por qu esta librera se ha convertido en referencia son: - Proyecto enmarcado dentro de las soluciones de Spring Framework, y todo lo que ello con lleva: Cdigo y diseo del componente excelente Gran uso en proyectos de referencia dentro del sector Java Solucin madura (con versiones estables desde el ao 2003). Facilidad de configuracin y parametrizacin (gracias al uso de namespace para la configuracin y al uso del patrn dependency Injection). Integracin con los sistemas legacy de autenticacin ms importantes del mercado: BBDD, LDAP, CAS (para single sign-on), gestin de certificados, etc. Como todo componente realizado dentro de la familia Spring es de fcil uso y fcil extensibilidad. Gran cantidad de documentacin y ejemplo de soporte.

Una vez definidas las caractersticas principales que han convertido a Spring Security en la librera referente, para dar solucin a la seguridad de aplicaciones, pasaremos a comentar las principales funcionalidades que presenta la librera y una breve descripcin de cada una de ellas.

Autenticacin en Spring Security Antes de nada, definir que un proceso de autenticacin consiste en identificar a la entidad que realiza una accin sobre la aplicacin y garantizar que es quin dice ser. La entidad que realiza una accin sobre la aplicacin es conocida con el nombre de principal. Desde el punto de vista de la arquitectura del mdulo de seguridad, el componente principal es AuthenticationManager el cual es el componente encargado de implementar el proceso de autenticacin en las aplicaciones. Antes de describir como es el diseo de AuthenticationManager, es necesario introducir algunos componentes que juegan un especial rol, y que son necesarios para poder comprender el proceso de autenticacin dentro de Spring Security. Objeto Authentication. Dentro de este componente se guardan los datos asociados al principal, as como el conjunto de autoridades (roles) que posee dicho principal. Este objeto Authentication es en el que se apoya el AuthenticationManager para implementar el servicio de autenticacin. Objeto SecurityContextHolder. Este componente es el encargado de guardar los datos del principal y sus roles (autoridades) dentro del contexto de seguridad. Como hemos comentado, la informacin del principal y los roles asociados estn encapsulados dentro del objeto Authentication, por tanto el SecurityContextHolder guarda el objeto Authentication en el contexto

de seguridad. Normalmente, en casi todas las aplicaciones el contexto de seguridad coincide con el ThreadLocal, lo cual permite que la informacin que reside en el objeto Authentication pueda ser consultada en todo momento por cualquier componente dentro de nuestra aplicacin. Objeto UserDetailsService. Como casi siempre en Spring, se produce un modelo de delegacin de responsabilidades, con lo que el objeto AuthenticationManager delega en el objeto UserDetails las labores de obtencin de la informacin del usuario sobre el repositorio de seguridad. Por ejemplo, si el repositorio de usuarios, credenciales y roles de la aplicacin estn en BBDD, el objeto UserDetails ser el encargado de realizar las oportunas consultas que obtengan toda la informacin del principal a partir del esquema de BBDD correspondiente.

Volviendo al componente AuthenticationManager, este interfaz nicamente implementa el mtodo:


Authentication authenticate (Authentication authentication) throws AuthtenticationException;

Como puede ver el lector, el parmetro de entrada authentication bsicamente tendr los datos bsicos del principal (en un ejemplo sencillo el nombre de usuario peticionario). Con este dato, se proceder a obtener toda la informacin de credenciales asociadas con el principal, y se comprobar si dichas credenciales son correctas. En el caso que el sistema de seguridad sea basado en username y password, se comprobar que la password pasada por el usuario, es correcta (buscando para ello la credencial dentro del repositorio de seguridad configurado en la aplicacin). En el caso que el proceso de autenticacin no sea correcto (credenciales incorrectas o nombre de usuario no vlido) el componente lanzar la correspondiente AuthenticationException. En el caso que el proceso de autenticacin, por el contrario, sea correcto, se proceder a obtener los roles (autoridades) asociadas al principal y sern guardadas en el objeto Authentication, que ser devuelto por el AuthenticationManager. Finalmente este objeto Authentication ser guardado por el componente SecurityContextHolder en el contexto de seguridad oportuno (normalmente el ThreadLocal). Como anteriormente se coment, un modelo que se repite mucho en las soluciones de Spring es la delegacin de responsabilidades dentro de los distintos componentes de la arquitectura. En el caso del AuthenticationManager, se dispone de un conjunto de componentes ProviderManager los cuales son los encargados de implementar el proceso de autenticacin. Los objetos ProviderManager estn ms cercanos a la tecnologa usada para implementar el repositorio de seguridad de la aplicacin. As por ejemplo, si nuestro sistema de autenticacin est soportado mediante un directorio activo, dispondremos de un objeto LdapAuthenticationProvider encargado de realizar las labores de autenticacin contra dicho directorio activo. A continuacin se presenta un diagrama donde se ve la estructura de las clases envueltas en el proceso de autenticacin:

Diagrama de clases Autenticacin en Spring Security

Diagrama de colaboracin AuthenticationManager En el ltimo diagrama se puede observar como los distintos componentes colaboran entre s para implementar el proceso de autenticacin de una aplicacin. Por suerte, Spring Security viene con la implementacin de numerosos ProviderManager que dan cabida a la integracin con distintos sistemas de soporte para el proceso de autenticacin. Simplemente es necesario configurar dichos componentes para adaptarlos a la particularidad que pueda tener la aplicacin que estemos desarrollando.

Configuracin de Spring Security con namespace Una de las principales ventajas introducidas en la versin 2.5 de Spring Security es la inclusin de un namespace especfico, que da soporte a la configuracin de los distintos componentes que forman parte de la solucin de autenticacin y autorizacin de aplicaciones. Anteriormente a esta versin, era necesario definir un conjunto de beans muy extenso y exista la posibilidad de error en la gestin de las dependencias de los distintos beans. Gracias a la incorporacin de namespace a la solucin, al desarrollar se le abstrae de muchas particularidades internas de la solucin, proporcionando un fichero XML de configuracin (namespace) que hace la labor de parametrizacin mucho ms sencilla. As por ejemplo si queremos configurar un componente AuthenticationManager que acceda a BBDD para la obtencin de las credenciales y roles aplicacin bastara con incluir la siguiente porcin de cdigo XML dentro del fichero de configuracin de la librera:

Configuracin de AuthenticationManager mediante namespace

Como se puede ver en el ejemplo, el nico parmetro necesario para configurar el gestor de autenticacin es el datasource que indicar donde est el esquema de Base de datos donde reside el repositorio con los datos de seguridad. Como iremos viendo en este post, el fichero de configuracin permitira la configuracin de todos los elementos necesarios para realizar la autenticacin y autorizacin de una aplicacin web sobre protocolo http. Seguridad de aplicaciones web Aunque Spring Security permite introducir servicios de autenticacin y autorizacin independientemente de que la aplicacin sea web, a continuacin se detallar cmo se configura Spring Security para permitir introducir procesos de autenticacin y autorizacin en aplicaciones web que corren bajo el protocolo HTTP. Bien, lo primero que es necesario definir para proceder a autenticar y autorizar una aplicacin web con Spring Security es la definicin de un ServletFilter, concretamente DelegatingFilterProxy. Bsicamente lo que realiza este filtro es, como su propio nombre indica, de proxy entre un entorno gestionado por el contexto de servlets y un entorno gestionado por el contexto de aplicacin de Spring. Lo que permite este filtro, por tanto es que todos los componentes que forman parte de la arquitectura de Spring Security puedan ser definidos mediante los ficheros

XML de definicin de beans tpicos de Spring y las ventajas del uso del patrn DependencyInjection. Como se coment anteriormente, adicionalmente Spring Security permite una configuracin de los componentes mediante el uso de un namespace, el cual consiste bsicamente en un fichero XML que cumple un determinado esquema, el cul est preparado para la configuracin de los distintos componentes de la solucin de un modo sencillo. Por tanto, lo nico que se necesita para configurar los servicios de seguridad web es introducir la siguiente configuracin dentro del fichero XML de configuracin:

Configuracin de servicios de seguridad web En el ejemplo se puede ver como se configura el mecanismo de autenticacin basado en formulario. En el caso que se quiera establecer un mecanismo de autenticacin bsico, nicamente sera necesario introducir la etiqueta . Dentro de la configuracin, adicionalmente se puede ver como se pueden securizar urls mediante el uso de la etiqueta . Bsicamente esta etiqueta contiene el patrn 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 el usuario contenga uno de esos roles, sera suficiente para disponer de permiso para dicha URL. Dentro de este fichero de configuracin se pueden configurar las siguientes grandes funcionalidades: Funcionalidades remember-me las cuales darn soporte a permitir que el usuario pueda guardar las credenciales en el navegador, y as no tener que volver a introducirlas en el siguiente proceso de autenticacin. Usa un soporte de cookies con aplicacin de algoritmos hash para la salvaguarda de la informacin de la credencial. Seleccin del canal de seguridad. Mediante el uso del atributo requireschannel dentro de la etiqueta se puede exigir que determinadas URLs sean seguras dentro de la aplicacin. Spring Security hace las oportunas redirecciones que sean necesarias para el cambio de canal. Gestin de la sesin. o Control de los timeouts de sesin. Se le puede indicar una pgina cuando se realice una peticin de una sesin que est invalidada. o Control de la sesin concurrente. Es posible controlar el nmero de sesiones activas para un mismo usuario. Esto supone una proteccin

contra el ataque de fijacin de sesin: http://en.wikipedia.org/wiki/Session_fixation Soporte para OpenID

Desde el punto de vista de la arquitectura, Spring Security mantiene una cadena de filtros, cada uno de los cuales da cabida a una funcionalidad dentro de los procesos de autenticacin y autorizacin entre cada peticin y respuesta. Es posible modificar y extender la cadena de filtros para ajustarse a las necesidades particulares de cada aplicacin. As por ejemplo por destacar algunos mencionar los siguientes filtros: FilterSecurityInterceptor. Es el encargado de manejar la seguridad de los recursos HTTP. Bsicamente es el que maneja los elementos definidos anteriormente en el namespace. ExceptionTranslationFilter. Es el encarga de manejar las excepciones lanzadas por los interceptores de seguridad y proveer la respuesta HTTP correspondiente. SecurityContextPersistenceFilter: Es el responsable de guardar el contexto de seguridad entre peticiones. Bsicamente el contexto de seguridad es guardado a nivel de sesin.

Cadena de filtros

Como se puede ver en la figura, existen numerosos interceptores en la cadena, pero no vamos a comentar todos ellos en este post, con el objetivo de disponer de una visin ms global de la librera. Para ms detalle sobre dichos interceptores consultar la gua de referencia de Spring Security. En definitiva, toda la cadena de filtros es creada y aislada del programador mediante el uso del namespace. No obstante, y como se ha comentado antes, es posible modificar y extender la cadena de filtros para poder adaptarlo a las necesidades particulares de la aplicacin. A continuacin detallaremos el mdulo de autorizacin de Spring Security. Autorizacin en SpringSecurity A continuacin se presenta un diagrama de clases donde se define la arquitectura del mdulo de autorizacin en Spring Security.

Autorizacion Spring Security

Como se puede ver en la figura, el interfaz central es AbstractSecurityInterceptor. Bsicamente es una clase abstracta que representa las capacidades de autorizacin bsicas. Como se puede ver en la figura los objetos que se pueden securizar dentro de Spring Security son peticiones HTTP (FilterSecurityInterceptor) e invocaciones a mtodos, que se pueden realizar mediante MethodSecurityInterceptor y AspectJSecurityInterceptor.

Este interceptor delega en el interfaz AccessDecisionManager la decisin de autorizacin final. Este interfaz implementa un mtodo decide que bsicamente recibe un objeto Authentication representando al principal que accede a la peticin, un objeto seguro (url o ejecucin de mtodo) y una lista de atributos con metadatos de seguridad (bsicamente la lista de roles para los que se les puede dar acceso al recurso). A continuacin veamos el diseo definido para el componente AccessDecisionManager:

Como se puede ver en la figura, el sistema de autorizacin de Spring Security est basado en un sistema de Votos. Concretamente SpringSecurity viene con tres implementaciones de AccessDecisionManager: AffirmativeBased: En el caso de recibir un slo voto positivo, se le da acceso al recurso protegido.Se permite controlar el comportamiento en el caso que todos los votos son de abstencin. ConsensusBased: Ser necesario que haya ms votos positivos que negativos para dar acceso al recurso protegido. Se permite controlar el comportamiento en el caso que todos los votos son de abstencin. UnanimousBased: Es necesario que todos los votos sean positivos para dar acceso al recurso protegido. Se permite controlar el comportamiento en el caso que todos los votos son de abstencin.

Como se puede ver en la figura los componentes AccessDecisionManager usan AccessDecisionVoter. En concreto en Spring Security vienen dos implementaciones de AccessDecisionVoter: RoleVoter: Este componente simplemente comprueba si para cada rol especificado para proteger al recurso protegido lo presenta el principal que realiza la peticin. En tal caso emite un voto positivo. (Revisar el componente ). En el caso que el principal no tenga el rol el componente realizar un voto negativo. En concreto para el caso del componente se presenta un AffirmativeBased AccessDecisionManager, con lo que con que el principal disponga de un rol de los especificados en la lista, se proceder a dar permiso al recurso protegido (en este caso la URL). AuthenticatedVoter. Este componente permite diferenciar entre acceso annimo al recurso, completamente autenticado u autenticado mediante mecanismos remember-me (IS_AUTHENTICATED:ANONYMOUS, IS_AUTHENTICATED_REMEMBERED, IS_AUTHENTICATED_FULLY). As por ejemplo en el ejemplo expuesto anteriormente, se le permita a usuarios annimos acceder a la pgina de autenticacin del usuario. Esto normalmente suele ser necesario para aquellas pginas que necesitan tener un comportamiento diferente para usuarios autenticados, de usuarios no autenticad.

Todos los componentes del mdulo de autorizacin de SpringSecurity permiten ser extendidos para proveer mecanismos de autorizacin ms sofisticados. En resumen, para securizar recursos HTTP, el sistema de votos aplica una lgica OR, de tal manera que con que el principal disponga de al menos uno de los roles especificado en la lista de roles asociados al recurso protegido, el AccessDecisionManager se proceder a dar acceso a dicho recurso protegido. Adicionalmente, SpringSecurity permite el securizar invocaciones a mtodos, comnmente llamado seguridad a nivel de capa de servicio. Esto permitir que dispongamos de mecanismos de autorizacin de invocaciones de componentes que forman la capa de servicio, no quedndonos nicamente en la securizacin de componentes de la capa web de la aplicacin. Seguridad de la capa de servicio Existen cuatro formas distintas de securizar las ejecuciones de mtodos dentro de Spring Security: Configuracin de seguridad a nivel global (uso del namespace) Configuracin de seguridad usando el componente MethodSecurityInterceptor Configuracin de seguridad basada en anotaciones (JSR-250 SpringSecurity). Configuracin de seguridad a nivel de bean

A continuacin se muestra un ejemplo de cada una de ellas. Esta opcin permite una securizacin centralizada de todos los mtodos de la capa de servicio. Adicionalmente presenta una expresin AspectJ de definicin del pointcut, el cual permite aplicar de manera flexible seguridad a varios objetos. En el ejemplo expuesto se estn securizando todos los mtodos del paquete com.mycompany que acaben por Service e independientemente del nmero de parmetros que tenga el mtodo.

Configuracin de seguridad a nivel global (namespace) Otra opcin posible, aunque las expresiones no son tan potentes como el caso de AspectJ.

MethodSecurityInterceptor La principal desventaja de esta aproximacin es que por cada bean es necesario indicar los parmetros de seguridad necesarios a cada uno de los mtodos. Es por tanto, una solucin ms descentralizada y con ms cantidad de configuracin necesaria.

Seguridad a nivel de vean

Directamente sobre la clase que se quiere securizar se introducen anotaciones especficas (propias de Spring Security o las definidas por el estndar JSR-150). Es necesario dentro del namespace configurar los atributos secured-annotations o jsr250-annotations a enabled en el elemento mdel namespace.

Seguridad a nivel de anotacin

Con estas opciones, el nivel de seguridad disponible siempre es a nivel de rol (autoridad). Sin embargo, Spring Security 3.o introduce un nuevo mecanismo mucho ms potente que permite la introduccin de expresiones Spring-EL (nuevas en Spring 3.0) para securizar la invocacin de mtodos. Con este modelo, lo que se permite es disponer de expresiones ms completas para definir la seguridad a nivel de mtodo, existiendo la posibilidad de interactuar con los parmetros de entrada. As por ejemplo, con las expresiones Spring-EL, supongamos que disponemos de un mtodo de consulta de facturas de clientes. Resulta que dentro de los requisitos de seguridad de la aplicacin, se define que nicamente los administradores pueden imprimir facturas superiores a 5000 . Para este propsito Spring introduce las anotaciones @PreAuthorize, @PostAuthorize, @PreFilter y @PostFilter . Para el ejemplo expuesto anteriormente, la anotacin quedara de la siguiente manera: @PreAuthorize(hasRole(ADMIN) and #factura.importe>5000) public void imprimir(Factura factura); En cuanto a las anotaciones @PreFilter y @PostFilter se usan para filtrar elementos de una coleccin antes o despus de la ejecucin del mtodo. Pongamos un ejemplo, supongamos que de la lista de Facturas devueltas por un mtodo, se quieren filtrar aquellas que sean mayores de 5000, para esta funcionalidad sera necesario implementar una anotacin @PostFilter indicando la condicin anteriormente definida. Para finalizar nuestro recorrido por SpringSecurity, a continuacin se define cmo SpringSecurity mediante su sistema de control de acceso permite la securizacin de los objetos de dominio.

Seguridad de objetos de dominio mediante ACL A veces es necesario securizar los propios objetos de dominio de la aplicacin. En un supuesto ejemplo de facturas, supongamos que queremos controlar el acceso para que cada usuario vea las facturas de unos determinados clientes. Para ello, sera necesario introducir elementos de seguridad en cada uno de los objetos de dominio. Considerando que los objetos de dominio pueden ser potencialmente muy numerosos, las opciones con SpringSecurity que se abren son las siguientes: Escribir los mtodos de negocio, de tal manera que dentro de su implementacin se realicen las oportunas reglas de autorizacin sobre los objetos de dominio. La principal desventaja de esta opcin es que mezcla la propia lgica de negocio del dominio con la lgica de seguridad de los mismos, lo cual ahonda en una falta de separacin de conceptos y una dificultad a la hora de realizar los procesos de testeo. Escribir un AccessDecisionVoter que fuerze la seguridad a partir de la lista de GrantedAuthorities (permisos de aplicacin) guardados en el objeto Authentication. Esta opcin necesitara el crear un objeto GrantedAuthority por cada objeto de dominio que queramos securizar. El problema, aunque conceptualmente es aceptable reside en la escalabilidad de la solucin, puesto que la cantidad de memoria necesaria para guardar los GrantedAuthority es muy alta. Escribir un AccessDecisionVoter que se encarga de forzar la seguridad a partir de la obtencin directa de los objetos de dominio que se quieren securizar. Por tanto, el componente AccessDecisionVoter dispondra de un objeto DAO para recuperar los datos de los objetos de dominio. Sin embargo, esto obliga a que haya un doble acceso a BBDD por invocacin de mtodo que hace que el rendimiento no sea el ms idneo.

Por tanto, para solucionar esta problemtica, SpringSecurity viene con un esquema de tablas (4 tablas en total) que permiten guardar los objetos de dominio, los permisos de la aplicacin y el cruce entre los distintos permisos y objetos de dominio necesarios para implementar la seguridad. Por defecto, el nivel de permisos que viene con la solucin son: CREATE, DELETE, READ, WRITE y ADMIN, aunque es sencillo implementar nuevos permisos. Adicionalmente, el sistema de control de acceso proporcionado por SpringSecurity viene con un conjunto de objetos que se encargan por un lado deabstraerte del modelo de datos subyacente, y por otro lado ofrece la lgica de servicio que permite la obtencin de los permisos sobre los objetos de un modo eficiente, puesto que la cantidad de informacin manejada para implementar esta funcionalidad es potencialmente alta. El sistema est integrado con el componente EHCache, lo que permite disponer de mecanismos de cach que optimizan la ejecucin de consultas, as como mecanismos tales como vistas materializadas, consultas jerrquicas y similares capacidades para el aumento del rendimiento de la solucin. A continuacin se plantea un ejemplo de un mtodo de lgica de negocio que es securizado usando las expresiones introducidas en el apartado anterior, y que permite filtrar el conjunto de objetos de dominio devuelto por el mtodo, restringiendo los elementos de la coleccin, para las que el usuario tiene permiso de lectura y

administracin. En este caso, el sistema de ACL se encargar de filtrar de todos los elementos de la coleccin devueltos por el mtodo, slo aquellos con permisos de lectura y administracin.

Listas de control de acceso

Para ms informacin de cmo se configura el mdulo ACL, consultar la gua de referencia de Spring Security o el ejemplo Contacts que viene incluido dentro del cdigo de SpringSecurity. El propsito de este post es comentar las posibilidades que presenta SpringSecurity sin entrar en los detalles de configuracin ms especficos. Conclusiones Como se ha podido ver a lo largo del artculo, SpringSecurity proporciona una librera con gran capacidad para la implementacin de los servicios de autenticacin y autorizacin de una aplicacin. Con una configuracin mnima es posible realizar la autenticacin de la aplicacin en BBDD, LDAP, integracin con CAS para Single Sign On, etc Asimismo mediante mecanismos declarativos es posible la securizacin de los recursos de una aplicacin web, con la potencia que dan las expresiones AspectJ de definicin de pointcuts. Asimismo todas las funcionalidades de remember-me y de gestin de usuarios annimos est implicita dentro de la solucin, con lo que prcticamente no es necesario implementar componentes para dar cabida a dichas funcionalidades. Mediante mecanismos de programacin orientada a aspectos, se pueden securizar invocaciones a mtodos de la capa de servicio, y con el nuevo soporte de expresiones Spring-EL se permite, incluso implementar polticas de seguridad especficas del dominio. Finalmente, y para dar soporte a la securizacin de objetos del dominio, SpringSecurity viene con todo el soporte necesario para evitar implementar soluciones especficas a las aplicaciones y garantizando que el rendimiento de la aplicacin es ptimo. Y todo ello aderezado con la excelencia en la codificacin de las clases que forman parte de la solucin y un diseo espectacular muy modular que permite la extensibilidad de cualquier funcionalidad dentro del framework de manera muy sencilla. En definitiva, enhorabuena de nuevo al equipo de Spring Framework, realizando una solucin que considero de referencia dentro de la tecnologa Java para la seguridad de aplicaciones Java.
A los lectores de este post, agradecer que introduzcan todos los comentarios que crean convenientes con el objeto de que el artculo sea lo ms completo y til posible, para que por lo menos, alguien que no conociera SpringSecurity pueda tener un primer contacto con l y conozca las posibilidades de esta magnfica librera.

Você também pode gostar