Configuración de Spring Security
- Área: Control de Acceso y Autenticación
- Carácter del recurso: Recomendado
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
Filtro | Clase | Elemento del Namespace |
---|---|---|
CHANNEL_FILTER | ChannelProcessingFilter | http/intercept-url |
CONCURRENT_SESSION_FILTER | ConcurrentSessionFilter | http/concurrent-session-control |
SESSION_CONTEXT_INTEGRATION_FILTER | HttpSessionContextIntegrationFilter | http |
LOGOUT_FILTER | LogoutFilter | http/logout |
X509_FILTER | X509PreAuthenticatedProcessigFilter | http/x509 |
PRE_AUTH_FILTER | AstractPreAuthenticatedProcessingFilter Subclasses | N/A |
CAS_PROCESSING_FILTER | CasProcessingFilter | N/A |
AUTHENTICATION_PROCESSING_FILTER | AuthenticationProcessingFilter | http/form-login |
BASIC_PROCESSING_FILTER | BasicProcessingFilter | http/http-basic |
SERVLET_API_SUPPORT_FILTER | SecurityContextHolderAwareRequestFilter | http/@servlet-api-provision |
REMEMBER_ME_FILTER | RememberMeProcessingFilter | http/remember-me |
ANONYMOUS_FILTER | AnonymousProcessingFilter | http/anonymous |
EXCEPTION_TRANSLATION_FILTER | ExceptionTranslationFilter | http |
NTLM_FILTER | NtlmProcessingFilter | N/A |
FILTER_SECURITY_INTERCEPTOR | FilterSecurityInterceptor | http |
SWITCH_USER_FILTER | SwitchUserProcessingFilter | N/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>
Enlaces externos
Contenidos relacionados
Código | Título | Tipo | Carácter | |
---|---|---|---|---|
PAUT-0234 | Autorizaciones personalizadas | Pauta | Directriz | No Recomendada |