Configuración de Spring Security

RECU-0213 (Recurso Referencia)

Descripción

Introducción

Spring Security es un framework de apoyo al marco de trabajo Spring, que dota al mismo de una serie servicios de seguridad aplicables para sistemas basados en la arquitectura basados en J2EE, enfocado particularmente sobre proyectos construidos usando SpringFramework. De esta dependencia, se minimiza la curva de aprendizaje si ya es conocido Spring.

Los procesos de seguridad están destinados principalmente, a comprobar la identidad del usuario mediante la autenticación y los permisos asociados al mismo mediante la autorización. La autorización es dependiente de la autenticación ya que se produce posteriormente a su proceso.

Por regla general muchos de estos modelos de autenticación son proporcionados por terceros o son desarrollados por estándares importantes como el IETF adicionalmente, Spring Security proporciona su propio conjunto de características de autenticación. Específicamente, Spring Security actualmente soporta integración de autenticación con todas las siguientes tecnologías:

  • HTTP BASIC authentication headers (an IEFT RFC-based standard).
  • HTTP Digest authentication headers (an IEFT RFC-based standard).
  • HTTP X.509 client certificate exchange (an IEFT RFC-based standard).
  • LDAP (un enfoque muy comun para necesidades de autenticación multiplataforma, especificamente en entornos extensos).
  • Form-based authentication (necesario para interfaces de usuario simples).
  • OpenID authentication.
  • Computer Associates Siteminder.
  • JA-SIG Central Authentication Service.
  • Transparent authentication context propagation for Remote Method Invocation (RMI) and HttpInvoker.
  • Automatic "remember-me" authentication.
  • Anonymous authentication.
  • Run-as authentication.
  • Java Authentication and Authorization Service (JAAS)
  • Container integration with JBoss, Jetty, Resin and Tomcat (tambien podemos usar autenticación gestionada por el contenedor)
  • Java Open Source Single Sign On (JOSSO)*
  • OpenNMS Network Management Platform*
  • AppFuse*
  • AndroMDA*
  • Mule ESB*
  • Direct Web Request (DWR)*
  • Grails*
  • Tapestry*
  • JTrac*
  • Jasypt*
  • Roller*
  • Elastic Plath*
  • Atlassian Crowd*
  • Nuestros propios sistemas de autenticación.

(*Indica proporcionado por un tercero)

Spring Security tiene un alto grado de aceptación entre la comunidad de desarrolladores por su gran flexibilidad sobre los modelos de autenticación. De esta manera, permite una rápida integración de las soluciones que presentan ante los requerimientos de los clientes potenciales, sin implicar una migración de los sistemas a un determinado entorno. Además es una plataforma abierta y en constante evolución, lo que permite ir añadiendo nuevos mecanismos de autenticación, o directamente programar los propios de manera poco compleja

En ocasiones un proceso simple de autenticación no es eficiente. Hay que controlar como se relaciona el usuario con la aplicación. Puede resultar interesante como llegan las solicitudes , si son automatizadas o por medio de una persona, asegurar que se realizan mediante el protocolo Http. Para completar estos objetivos, Spring Security proporciona "canales de seguridad" automáticos integrándose con JCaptcha para detección de usuarios humanos.

SpringSecurity también facilita el proceso de la autorización. Para ello, aporta tres características esenciales: Autorización en base a solicitudes web, autorización en base a llamadas, autorización en base al acceso a instancias.

Espacio de nombres (Namespace) de seguridad

Un elemento del namespace puede ser usado para permitir configurar de forma concisa un bean , de forma individual, o para definir una sintaxis de configuración más cercana al dominio del problema escondiendo la complejidad de la misma al usuario. Un elemento simple puede ocultar el hecho de que múltiples beans y pasos del procedimiento han sido añadidos al contexto de la aplicación

Para empezar a usar el namespace en el contexto de su aplicación ese necesario que añada el esquema siguiente al contexto de su aplicación:

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

Diseño del espacio de nombres

El espacio de nombres está diseñado para capturar los usos más comunes del framework y para proporcionar una simple y concisa sintaxis para adaptarlos a la aplicación. El diseño se basa en la gran escala de dependencias en el framework, y puede ser dividido en las siguientes áreas:

  • Web/HTTP Security La parte mas compleja. Configura los filtros y los "service beans" usados para aplicar los mecanismos de autenticación.
  • Business Object Security Opciones para asegurar la capa de servicio
  • AuthenticationManager Maneja las peticiones de autenticación de otras partes del framework
  • AccessDecisionManager Proporciona acceso a las decisiones para la web y la seguridad del método. Una por defecto será registrada, pero también se puede optar por utilizar una personalizada, declarada con la sintaxis normal de spring bean
  • AuthenticationProviders Mecanismos con los que el AuthenticationManager autentica los usuarios
  • UserDetailsService estrechamente relacionada con los AuthenticationProviders, pero a menudo también requiere de otros beans.

Configurando el Namespace de seguridad

En primer lugar es necesario modificar el "web.xml" y añadir los filtros de seguridad

<filter>
  <display-name>seguridadSpring</display-name>
  <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>

Se añaden los usuarios mediante el proveedor de servicios, asignándole un password y los criterios de autorización de permisos. Esta información será utilizada por el authentication-manager en los procesos de autenticación

<authentication-manager>
   <authentication-provider>
      <user-service>
         <user name="jimi" password="jimispassword" authorities="ROLE_USER, ROLE_ADMIN" />
         <user name="bob" password="bobspassword" authorities="ROLE_USER" />
      </user-service>
   </authentication-provider>
</authentication-manager>

El authentication-provider puede ser configurado para que sea una base de datos, o la implementación de seguridad que configuremos.

Mediante el http introducimos los patrones a controlar con los permisos asociados por el framework de seguridad. Aquí se pueden indicar la página de inicio, la situación tras un intento de login, etc

<sec:http auto-config="true">
        <sec:intercept-url pattern="/cambio.jsp"     access="ROLE_ADMIN"/>
        <sec:form-login    login-page="/conexion.jsp"
                           authentication-failure-url="/error.jsp"
                           login-processing-url="/seguridad"/>
    </sec:http>

Otros aspectos de la configuración de Spring Security

A continuación se ofrecen diversos aspectos configurables en Spring Security

Control sobre la sesión

Se puede controlar el acceso de sesión minimizando a una única sesión activa. Para ello es necesario modificar el web.xml e incluir un listener específico:

<listener>
   <listener-class>
      org.springframework.security.web.session.HttpSessionEventPublisher
   </listener-class>
</listener>

y a continuación indicarle la restricción en el contexto de la aplicación

<http>
  ...
  <concurrent-session-control max-sessions="1" />
</http>

OpenID Login

EL Namespaces soporta OpenID Login con una leve modificación. Es necesario tener nuestro propio servidor de OpenID

<http>
    <intercept-url pattern="/**" access="ROLE_USER" />
    <openid-login />
</http>

Añadir criptografía al password de usuario

A menudo pueden ser codificadas las claves de usuario a partir de un algoritmo de hashing. Esto es soportado por el <password-encoder>. En el ejemplo siguiente , con SHA

<authentication-provider>
  <password-encoder hash="sha"/>
  <user-service>
    <user name="jimi" password="d7e6351eaa13189a5a3641bab846c8e8c69ba39f" authorities="ROLE_USER, ROLE_ADMIN" />
    <user name="bob" password="4e7421b1b8765d8f9406d87e7cc6aa784c4ab97f" authorities="ROLE_USER" />
  </user-service>
</authentication-provider>

Tabla de filtros

A continuación se ofrece la tabla de filtros básicos de configuración. Los filtros se ejecutan de forma ordenada, así que es interesante situar en la parte alta los más solicitados para mejorar la ejecución

FiltroClaseElemento del Namespace
CHANNEL_FILTERChannelProcessingFilterhttp/intercept-url
CONCURRENT_SESSION_FILTERConcurrentSessionFilterhttp/concurrent-session-control
SESSION_CONTEXT_INTEGRATION_FILTERHttpSessionContextIntegrationFilterhttp
LOGOUT_FILTERLogoutFilterhttp/logout
X509_FILTERX509PreAuthenticatedProcessigFilterhttp/x509
PRE_AUTH_FILTERAstractPreAuthenticatedProcessingFilter SubclassesN/A
CAS_PROCESSING_FILTERCasProcessingFilterN/A
AUTHENTICATION_PROCESSING_FILTERAuthenticationProcessingFilterhttp/form-login
BASIC_PROCESSING_FILTERBasicProcessingFilterhttp/http-basic
SERVLET_API_SUPPORT_FILTERSecurityContextHolderAwareRequestFilterhttp/@servlet-api-provision
REMEMBER_ME_FILTERRememberMeProcessingFilterhttp/remember-me
ANONYMOUS_FILTERAnonymousProcessingFilterhttp/anonymous
EXCEPTION_TRANSLATION_FILTERExceptionTranslationFilterhttp
NTLM_FILTERNtlmProcessingFilterN/A
FILTER_SECURITY_INTERCEPTORFilterSecurityInterceptorhttp
SWITCH_USER_FILTERSwitchUserProcessingFilterN/A

Ejemplos

A continuación vamos a realizar un breve ejemplo de configuración de Spring Security.

  • Añadir dentro del fichero Web.xml la dirección de la configuración de seguridad y añadir los filtros
<context-param>
    <param-name>contextConfigLocation</param-name>
    <param-value>/WEB-INF/applicationContext-security.xml</param-value>
  </context-param>
<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>
  • Crear el fichero con la configuración de seguridad, applicationContext-security.xml
<!--  CONFIGURACION VALIDA PARA SPRING SECURITY 2.0 con JDBC --> 
<?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"
    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">
 
   <!--  CONFIGURACION VALIDA PARA SPRING SECURITY 2.0 con JDBC   -->
 
  <http auto-config="true" access-denied-page="/web/error.do">
       <intercept-url pattern="/" access="IS_AUTHENTICATED_ANONYMOUSLY" />
        <intercept-url pattern="/login.do" access="IS_AUTHENTICATED_ANONYMOUSLY" />
        <intercept-url pattern="/j_spring_security_switch_user"
            access="ROLE_SUPERVISOR" />       
        <intercept-url pattern="/web/css/**" access="ROLE_WEBMASTER" />
        <intercept-url pattern="/templates/**" access="ROLE_WEBMASTER" />
        <intercept-url pattern="/web/error/**" access="ROLE_USER" />   
 
    <form-login login-page="/login.do" default-target-url='/web/index.do'
            authentication-failure-url="/login.do?login_error=1"  />
    <logout logout-success-url="/" invalidate-session="true"/>
      </http>
 
  <authentication-provider user-service-ref="userService" />
 
  <!-- MYSQL -->
 
  <beans:bean id="securityDataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource">
    <beans:property name="driverClassName" value="org.gjt.mm.mysql.Driver" />
    <beans:property name="url" value="jdbc:mysql://localhost/test" />
    <beans:property name="username" value="root" />
    <beans:property name="password" value="" />
  </beans:bean> 
  <jdbc-user-service id="userService"
    data-source-ref="securityDataSource"   
     group-authorities-by-username-query="SELECT
                      g.nombre,
                      a.rol
                    FROM
                      dbo.bm_usuario u
                      INNER JOIN dbo.bm_grupo_usuario ug ON (u.id_usuario = ug.id_usuario)
                      INNER JOIN dbo.bm_grupo g ON (ug.id_grupo = g.id_grupo)
                      INNER JOIN dbo.bm_grupos_roles ON (g.id_grupo = dbo.bm_grupos_roles.id_grupo)
                      INNER JOIN dbo.bm_roles a ON (dbo.bm_grupos_roles.id_rol = a.id_rol)
                    WHERE
                      u.nombreUsuario = ? "
        users-by-username-query="SELECT
                      u.nombreUsuario AS Login,
                      u.password AS Password,
                      u.enabled AS Enabled
                    FROM
                      dbo.bm_usuario u
                    WHERE
                      u.nombreUsuario = ?"
        authorities-by-username-query="SELECT
                       u.nombreUsuario,
                        au.rol
                    FROM
                      dbo.bm_usuario_roles ua
                      INNER JOIN dbo.bm_usuario u ON (ua.id_usuario = u.id_usuario)
                      INNER JOIN dbo.bm_roles au ON (ua.id_rol = au.id_rol)
                    WHERE
                      u.nombreUsuario = ? " />
 
 
</beans:beans>

Contenidos relacionados

Pautas
Área: Desarrollo » Seguridad » Control de Acceso y Autenticación
Código Título Tipo Carácter
PAUT-0234 Autorizaciones personalizadas Pauta Directriz No Recomendada