Sunteți pe pagina 1din 20

Token con caducidad en Spring Security

0. ndice de contenidos.

1. Introduccin. 2. Entorno. 3. Proceso de autenticacin en Spring Security. 4. Configuracin de nuestro mecanismo de autenticacin. 5. Implementacin del mecanismo de autenticacin. 6. Conclusiones

1. Introduccin
Hoy en da ya sabemos que los mecanismos de autenticacin de las distintas aplicaciones pueden ser tan complejos o simples como podamos imginar. Tenemos la autenticacin bsica que ofrecen los propios navegadores, la comunmente utilizada de un formulario de usuario y contrasea, contra LDAP o Active Directory, etc. Incluso podemos tener combinacin de varios de estos mecanismos de seguridad o hacer extensiones de los mismos. Por suerte, SpringSecurity nos ofrece ya una amplia variedad de mecanismos de autenticacin que nos simplifican gran parte del trabajo. As que slo tenemos que configurarlos y/o hacer nuestras propias extensiones o modificaciones en caso de ser necesario. El objetivo de este tutorial es la introduccin de un token con un tiempo de caducidad para que el proceso de login se realice en un periodo de tiempo mximo. Esto es til cuando tenemos mecanismos de autenticacin automticos, de forma que limitamos la ventana de tiempo para el acceso a nuestra aplicacin. Antes de seguir, tengo que dejar claro que esto por s mismo no se puede considerar un mecanismo de autenticacin, realmente es un complemento a un mecanismo de autenticacin ya existente. Por lo que nuestro sistema ser tan seguro como sea ese mecanismo de autenticacin; y con este token de caducidad lo que hacemos es aumentar un poco su seguridad limitando el tiempo en el que permitimos acceder a la aplicacin. Como el mecanismo de autenticacin ms extendido es el de un formulario con usuario y contrasea, voy a tomar ste como mecanismo base. Extenderemos esta forma de autenticacin aadiendo un token con caducidad que establezca un tiempo mximo para el proceso de login, desde que se inicia pidiendo la autenticacin al usuario, hasta que se recibe de este su usuario y contrasea.

2. Entorno
Este tutorial est escrito usando el siguiente entorno:

Hardware: Porttil MacBook Pro 15' (2 GHz Intel Core i7, 8GB DDR3 SDRAM). Sistema Operativo: Mac OS X Lion 10.7.1 Spring Security 3.1.0.RC2 JSF 2.1.2

3. Proceso de autenticacin en Spring Security.


Antes de nada, voy a explicar brvemente cmo funciona el proceso de autenticacin en Spring Security. Este proceso se basa en un conjunto de interfaces y clases que interactan conjuntamente en un orden establecido para terminar decidiendo si una peticin tiene o no acceso. Spring realiza esto mediante una cadena de filtros en los que se irn haciendo las distintas acciones y comprobaciones necesarias hasta decidir si la autenticacin es correcta o no. En este proceso podemos identificar bsicamente a 3 actores principales:

AuthenticationFilter: Es el responsable de crear una instancia concreta del usuario y sus credenciales de autenticacin. AuthenticationManager: Responsable de la validacin del usuario y credenciales y rellenar los permisos/roles que tiene el usuario o de lanzar los distintos tipos de excepciones en caso de fallo en la autenticacin. Esto lo hace apoyndose en uno o varios proveedores de autenticacin. AuthenticationProvider: Es en quien se delega la correcta validacin del usuario y recuperacin de roles.

Este proceso a alto nivel sera:

1.- El filtro de seguridad intercepta la peticin de autenticacin. Crea una instancia de Authentication para su validacin. 2.- El filtro de seguridad pasa al AuthenticationManager el objeto creado para que realice su validacin. El AuthenticationManager delegar esta validacin al proveedor o proveedores de autenticacin. 3.- El proveedor de autenticacin comprobar si los datos de autenticacin son correctos. En caso de haber algn tipo de error lanzar una excepcin. 4.- El filtro de seguridad comprueba el resultado de la autenticacin solicitada al AuthenticationManager. Si se produjo una excepcin redirigir el flujo al AuthenticationFailureHandler y si hubo xito al AuthenticationSuccessHanlder.

4. Configuracin de nuestro mecanismo de autenticacin.


Como sabis, en Spring utilizamos un fichero de configuracin. As que en el caso de Spring Security no iba a ser distinto. Aqu os pongo el fichero de configuracin que vamos a utilizar en nuestro ejemplo, luego pasar a contar cul es cada uno de los elementos del fichero relacionados con el proceso de autenticacin.

? 1 <?xml version="1.0" encoding="UTF-8"?> 2 <beans:beans xmlns="http://www.springframework.org/schema/security" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 3 xmlns:beans="http://www.springframework.org/schema/beans" 4 xmlns:context="http://www.springframework.org/schema/context" 5 xmlns:aop="http://www.springframework.org/schema/aop" xsi:schemaLocation="http://www.springframework.org/schema/beans 6 http://www.springframework.org/schema/beans/spring-beans.xsd 7 http://www.springframework.org/schema/security 8 http://www.springframework.org/schema/security/spring-security-3.1.xsd 9 http://www.springframework.org/schema/context 1 http://www.springframework.org/schema/context/spring-context.xsd http://www.springframework.org/schema/aop 0 http://www.springframework.org/schema/aop/spring-aop.xsd"> 1 1 <context:annotation-config /> 1 2 <aop:aspectj-autoproxy /> 1 3 <context:component-scan base-package="com.autentia.tutoriales" /> 1 4 <http access-denied-page="/_403.xhtml" auto-config="false" entry-point-ref="LoginUrlAuthenticationEntryPoint"> 1 <custom-filter ref="authenticationFilter" 5 position="FORM_LOGIN_FILTER"></custom-filter> 1 <intercept-url pattern="/*" access="IS_AUTHENTICATED_FULLY" /> 6 </http> 1 <beans:bean id="LoginUrlAuthenticationEntryPoint" 7 class="org.springframework.security.web.authentication.LoginUrlA 1 uthenticationEntryPoint"> 8 <beans:property name="loginFormUrl" value="/login.xhtml" /> 1 </beans:bean> 9 2 <beans:bean id="authenticationFilter" class="com.autentia.tutoriales.UsernamePasswordWithTimeoutAuthen 0 2 ticationFilter"> <beans:property name="authenticationManager" 1 ref="authenticationManager" /> 2 <beans:property name="authenticationSuccessHandler" 2 ref="authenticationSuccessHandler" /> <beans:property name="authenticationFailureHandler" 2 ref="authenticationFailureHandler" /> 3 <beans:property name="filterProcessesUrl" value="/login" /> 2 <beans:property name="usernameParameter" value="username" /> 4 <beans:property name="passwordParameter" value="passwword" /> <beans:property name="timeoutParameter" value="timeout" /> 2 </beans:bean> 5 2 <beans:bean id="authenticationFailureHandler" 6 class="com.autentia.tutoriales.AutentiaAuthenticationFailureHand 2 ler"> 7 <beans:property name="defaultFailureUrl" value="/bad_credentials.html"/> 2

<beans:property name="expiredUrl" value="/login_timeout.html"/> 8 </beans:bean> 2 9 <beans:bean id="authenticationSuccessHandler" 3 class="com.autentia.tutoriales.AutentiaAuthenticationSuccessHand 0 ler"> </beans:bean> 3 1 3 <beans:bean id="authenticationProvider" 2 class="com.autentia.tutoriales.AutentiaAuthenticationProvider"> 3 <beans:property name="nonceValiditySeconds" value="10"/> 3 <beans:property name="key" value="KEY"/> 3 </beans:bean> 4 <authentication-manager alias="authenticationManager"> 3 <authentication-provider ref="authenticationProvider"/> 5 </authentication-manager> 3 </beans:beans> 6 3 7 3 8 3 9 4 0 4 1 4 2 4 3 4 4 4 5 4 6 4 7 4 8 4 9 5 0 5 1

5 2 5 3 5 4 5 5 5 6 5 7 5 8 Respecto al mecanismo de seguridad en el fichero podemos ver:


Lnea 16: Elemento que nos define cmo va a ser la autenticacin de nuestra aplicacin web por HTTP. Lnea 18: Establece la referencia al filtro de autenticacin. Lnea 19: Se definen cuales sn los recursos protegidos y quines tendrn acceso a ellos. En este caso se protege toda la aplicacin y basta con que el usuario est autenticado para que pueda acceder a los mismos. Lnea 22: Define cul va a ser el punto de entrada para la autenticacin. En este caso se redirige a la pgina /login.xhtml Lnea 27: Aqu definimos cual va a ser el filtro de autenticacin responsable de formar un objeto con los parmetos recibidos por el usuario (username,password,timeout), pasarlo al AuthenticationManager para su validacin y finalmente delegar el final del proceso dependiendo de si ha habido o no error de autenticacin (authenticationSuccessHandler y authenticationFailureHandler). Lnea 38: Bean responsable de tratar los intentos de autenticacin que han fallado y redirigir a la pgina de error. Lnea 44: Define cual va a ser el proveedor de autenticacin responsable de comprobar que el usuario es vlido y recuperar sus roles. En nuestro caso indicamos adems el tiempo mximo para el proceso de login (nonceValiditySeconds) y la clave utilizada para generar una firma y evitar que el token pueda ser manipulado. Lnea 50: Indica que vamos a utilizar el AuthenticationManager por defecto de Spring y que este va a utilizar como proveedor de autenticacin al que hemos definido en la lnea 44.

5. Implementacin del mecanismo de autenticacin.


Pus como podis ver en el fichero de configuracin, tenemos alguna que otra clase que hay que implementar. El "EntryPoint" que utilizamos es el propio de Spring, as que lo primero que tenemos que implementar es el filtro. Como hemos dicho, vamos a hacer una extensin de la autenticacin por usuario y contrasea, as que como Spring ya nos ofrece

un filtro para este tipo de autenticacin, lo que hacemos es directamente heredar de l y sobreescribir aquello que nos haga falta. Bsicamente lo realmente importante en el filtro es el mtodo "attempAuthentication(..)". ste ser casi identico al de Spring salvo por un par de detalles, adems de recuperar el usuario y la contrasea, se debe recuperar el timeout y con esto formar un objeto de autenticacin que ya lleve informado el timeout. As que el filtro quedar: ? 1 2 3 4 5 6 7 8 9 1 0 1 1 1 2 1 3 1 4 1 5 1 6 1 7 1 8 1 9 2 0 2 1 2 2 2 3 2 4

package com.autentia.tutoriales; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import org.springframework.security.authentication.AuthenticationServiceExcept ion; import org.springframework.security.core.Authentication; import org.springframework.security.core.AuthenticationException; import org.springframework.security.web.authentication.UsernamePasswordAuthent icationFilter; public class UsernamePasswordWithTimeoutAuthenticationFilter extends UsernamePasswordAuthenticationFilter { private String timeoutParameter = "timeout"; private boolean postOnly; @Override public void setPostOnly(boolean postOnly) { super.setPostOnly(postOnly); this.postOnly = postOnly; } @Override public Authentication attemptAuthentication(HttpServletRequest request, HttpServletResponse response) throws AuthenticationException { if (postOnly && !"POST".equals(request.getMethod())) { throw new AuthenticationServiceException( "Authentication method not supported: " + request.getMethod()); } String username = obtainUsername(request); String password = obtainPassword(request); final String timeout = obtainTimeout(request); if (username == null) { username = ""; }

if (password == null) { 2 password = ""; 5 } 2 6 username = username.trim(); 2 7 final UsernamePasswordWithTimeoutAuthenticationToken authRequest 2 = new UsernamePasswordWithTimeoutAuthenticationToken( username, password, timeout); 8 2 setDetails(request, authRequest); 9 3 return 0 this.getAuthenticationManager().authenticate(authRequest); 3 } 1 protected String obtainTimeout(HttpServletRequest request) { 3 return request.getParameter(timeoutParameter); 2 } 3 3 public void setTimeoutParameter(String timeoutParameter) { 3 this.timeoutParameter = timeoutParameter; 4 } 3} 5 3 6 3 7 3 8 3 9 4 0 4 1 4 2 4 3 4 4 4 5 4 6 4 7 4

8 4 9 5 0 5 1 5 2 5 3 5 4 5 5 5 6 5 7 5 8 5 9 6 0 6 1 Como vis el filtro crea una instancia de un token de autenticacin que adems de usuario y contrasea tiene un timeout. Este token lo implementamos tambin heredando del token que ofrece Spring para usuario y contrasea, de forma que lo nico que hacemos es extenderlo para que tenga el timeout. ? 1 2 3 4 5 6 7 8 9 1 0 1 1
package com.autentia.tutoriales; import org.springframework.security.authentication.UsernamePasswordAuthenticat ionToken; public class UsernamePasswordWithTimeoutAuthenticationToken extends UsernamePasswordAuthenticationToken { private String timeout; public UsernamePasswordWithTimeoutAuthenticationToken(Object principal, Object credentials) { super(principal, credentials);

this.timeout=null; 1 } 2 1 public UsernamePasswordWithTimeoutAuthenticationToken(Object 3 principal, 1 Object credentials, String timeout) { this(principal, credentials); 4 this.timeout=timeout; 1 } 5 1 public String getTimeout() { 6 return timeout; 1 } 7 } 1 8 1 9 2 0 2 1 2 2 2 3 2 4 2 5

Ahora nos vamos a encargar de los dos responsables del post-proceso de una autenticacin con xito o con error. Para esto tambin nos apoyamos en las clases de Spring de las cules extendemos nuestras propias clases. En caso de xito: (Se realizara la lgica del intento de autenticacin correcta y luego se redirige a una pgina de bienvenida) ? 1 2 3 4 5 6 7 8 9 1

package com.autentia.tutoriales; import java.io.IOException; import javax.servlet.ServletException; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import org.springframework.security.core.Authentication; import org.springframework.security.web.authentication.AuthenticationSuccessHa ndler; import org.springframework.stereotype.Service;

0 1 1 1 2 1 3 1 4 1 5 1 6 1 7 1 8 1 9 2 0

@Service public class AutentiaAuthenticationSuccessHandler implements AuthenticationSuccessHandler { @Override public final void onAuthenticationSuccess(HttpServletRequest request, HttpServletResponse response, Authentication authentication) throws IOException, ServletException { //lgica de tratamiento de autenticacin correcta response.sendRedirect(response.encodeRedirectURL("welcome.xhtml ")); } }

Para el caso de un intento de autenticacin errnea: (Se redirecciona a una pgina de error de autenticacin o de timeout dependiendo del tipo de error) ? 1 2 3 4 5 6 7 8 9 1 0 1 1 1 2 1 3 1 4 1 5

package com.autentia.tutoriales; import java.io.IOException; import javax.servlet.ServletException; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import org.springframework.security.core.AuthenticationException; import org.springframework.security.web.authentication.SimpleUrlAuthentication FailureHandler; import org.springframework.security.web.authentication.www.NonceExpiredExcepti on; public class AutentiaAuthenticationFailureHandler extends SimpleUrlAuthenticationFailureHandler { private String defaultFailureUrl; private String expiredUrl; @Override public void onAuthenticationFailure(HttpServletRequest request, HttpServletResponse response, AuthenticationException exception) throws IOException,

1 6 1 7 1 8 1 9 2 0 2 1 2 2 2 3 2 4 2 5 2 6 2 7 2 8 2 9 3 0 3 1 3 2 3 3 3 4 3 5 3 6 3 7 3 8 3

ServletException { final String failureUrl=getFailureUrl(exception); if (failureUrl == null) { logger.debug("No failure URL set, sending 401 Unauthorized error"); response.sendError(HttpServletResponse.SC_UNAUTHORIZED, "Authentication Failed: " + exception.getMessage()); } else { saveException(request, exception); if (isUseForward()) { logger.debug("Forwarding to " + failureUrl); request.getRequestDispatcher(failureUrl).forward(reques t, response); } else { logger.debug("Redirecting to " + failureUrl); getRedirectStrategy().sendRedirect(request, response, failureUrl); } } } @Override public void setDefaultFailureUrl(String defaultFailureUrl) { super.setDefaultFailureUrl(defaultFailureUrl); this.defaultFailureUrl = defaultFailureUrl; } private String getFailureUrl(AuthenticationException exception) { if(exception instanceof NonceExpiredException){ return expiredUrl; } return defaultFailureUrl; } public void setExpiredUrl(String expiredUrl) { this.expiredUrl = expiredUrl; } }

9 4 0 4 1 4 2 4 3 4 4 4 5 4 6 4 7 4 8 4 9 5 0 5 1 5 2 5 3 5 4 5 5 Ahora ya slo nos queda la implementacin del proveedor de autenticacin, que ser el responsable de controlar que el token de caducidad sea correcto y que no se ha superado el timeout establecido. Para la generacin y comprobacin de este token, nos hemos basado en como Spring hace lo mismo para el tipo de autenticacin DigestAuthentication, pero que no lo implementa en otros tipos de autenticacin, por eso nos lo estamos teniendo que implementar nosotros. La idea es generar un token de caducidad que no haga falta almacenar en el servidor para su posterior comprobacin. Es decir, se meter en un campo oculto del formulario y cuando ste se devuelva al servidor se comprobar su validez en el servidor. Para hacer esto tiene que ser autodefinido, es defir, debe contener la fecha de caducidad, y hay que protegerlo a posibles manipulaciones.

As que nuestro proveedor de autenticacin quedar de la siguiente forma: ? 1 package com.autentia.tutoriales; 2 3 import java.security.MessageDigest; java.security.NoSuchAlgorithmException; 4 import import java.util.HashSet; 5 import java.util.Set; 6 7 import org.apache.commons.lang.StringUtils; 8 import org.slf4j.Logger; 9 import org.slf4j.LoggerFactory; import org.springframework.context.support.MessageSourceAccessor; 10 import 11 org.springframework.security.authentication.AuthenticationProvider; 12 import 13 org.springframework.security.authentication.BadCredentialsException; 14 import org.springframework.security.authentication.UsernamePasswordAuthenticat 15 ionToken; 16 import org.springframework.security.core.Authentication; 17 import org.springframework.security.core.GrantedAuthority; 18 import org.springframework.security.core.SpringSecurityMessageSource; import org.springframework.security.crypto.codec.Base64; 19 import org.springframework.security.crypto.codec.Hex; 20 import 21 org.springframework.security.web.authentication.www.NonceExpiredExcepti 22 on; 23 import org.springframework.stereotype.Service; 24 @Service 25 public class AutentiaAuthenticationProvider implements 26 AuthenticationProvider { 27 private static final Logger Log = 28 LoggerFactory.getLogger(AutentiaAuthenticationProvider.class); 29 30 private static final String NONCE_FIELD_SEPARATOR = ":"; 31 32 private String key = "KEY"; 33 34 private long nonceValiditySeconds=10; 35 36 37 protected final MessageSourceAccessor messages = 38 SpringSecurityMessageSource.getAccessor(); 39 @Override 40 public final Authentication authenticate(Authentication 41 authentication) { 42 final UsernamePasswordWithTimeoutAuthenticationToken 43 authenticationToken = 44 (UsernamePasswordWithTimeoutAuthenticationToken)authentication;

validateTimeout(authenticationToken); 45 //lgica de comprobacin de usuario y contrasea 46 return createSuccessAuthentication(authenticationToken); 47 } 48 49 @Override public final boolean supports(Class<?> authentication) { 50 return 51 UsernamePasswordWithTimeoutAuthenticationToken.class.isAssignableFrom(a 52 uthentication); 53 } 54 55 public long getNonceValiditySeconds() { return nonceValiditySeconds; 56 } 57 58 public void setNonceValiditySeconds(long nonceValiditySeconds) { 59 this.nonceValiditySeconds = nonceValiditySeconds; 60 } 61 62 public String getKey() { return key; 63 } 64 65 public void setKey(String key) { 66 this.key = key; 67 } 68 private void validateTimeout( 69 UsernamePasswordWithTimeoutAuthenticationToken 70 authenticationToken) { 71 if(StringUtils.isEmpty( authenticationToken.getTimeout())){ 72 final String msg="Timeout signature not present."; 73 Log.error(msg); throw new BadCredentialsException(msg); 74 } 75 final long 76 timeOutTime=extractNonceValue(authenticationToken.getTimeout()); 77 78 if (isNonceExpired(timeOutTime)){ 79 final String msg="Login timeout"; Log.error(msg); 80 throw new NonceExpiredException(msg); 81 } 82 } 83 84 boolean isNonceExpired(final long timeoutTime) { 85 final long now = System.currentTimeMillis(); return timeoutTime < now; 86 } 87 88 private long extractNonceValue(final String nonce) { 89 // Check nonce was Base64 encoded (as sent by the filter) 90 if (!Base64.isBase64(nonce.getBytes())) { throw new 91

92 BadCredentialsException(messages.getMessage("DigestAuthenticationFilter 93 .nonceEncoding", new Object[]{nonce}, "Nonce is not encoded in 94 Base64; received nonce {0}")); 95 } 96 // Decode nonce from Base64 97 // format of nonce is: 98 // base64(expirationTime + ":" + md5Hex(expirationTime + ":" + 99 key)) 10 final String nonceAsPlainText = new 0 String(Base64.decode(nonce.getBytes())); final String[] nonceTokens = 10 org.springframework.util.StringUtils.delimitedListToStringArray(nonceAs 1 PlainText, NONCE_FIELD_SEPARATOR); 10 2 if (nonceTokens.length != 2) { 10 throw new 3 BadCredentialsException(messages.getMessage("DigestAuthenticationFilter 10 .nonceNotTwoTokens", new Object[]{nonceAsPlainText}, "Nonce 4 should have yielded two tokens but was {0}")); 10 } 5 10 // Extract expiry time from nonce long nonceExpiryTime; 6 try { 10 nonceExpiryTime = Long.valueOf(nonceTokens[0]); 7 } catch (NumberFormatException nfe) { 10 throw new 8 BadCredentialsException(messages.getMessage("DigestAuthenticationFilter 10 .nonceNotNumeric", new Object[]{nonceAsPlainText}, 9 "Nonce token should have yielded a numeric 11 first token, but was {0}"),nfe); 0 } 11 // Check signature of nonce matches this expiry time 1 final String expectedNonceSignature = md5Hex(nonceExpiryTime + 11 NONCE_FIELD_SEPARATOR + key); 2 11 if (!expectedNonceSignature.equals(nonceTokens[1])) { 3 throw new 11 BadCredentialsException(messages.getMessage("DigestAuthenticationFilter 4 .nonceCompromised", new Object[]{nonceAsPlainText}, "Nonce 11 token compromised {0}")); 5 } 11 6 return nonceExpiryTime; } 11 7 private Authentication 11 createSuccessAuthentication(UsernamePasswordAuthenticationToken 8 authenticationToken) { 11

final Set<GrantedAuthority> authorities = new 9 HashSet<GrantedAuthority>(); 12 //lgica de asignacin de roles en authorities 0 return new 12 UsernamePasswordAuthenticationToken(authenticationToken.getPrincipal(), authenticationToken.getCredentials(), authorities); 1 } 12 2 public String calculateNonce() { 12 final long expiryTime = System.currentTimeMillis() 3 + (nonceValiditySeconds * 1000); 12 final String signatureValue = md5Hex(new 4 StringBuilder().append(expiryTime).append(NONCE_FIELD_SEPARATOR).append 12 (key).toString()); final String nonceValue = new 5 StringBuilder().append(expiryTime).append(NONCE_FIELD_SEPARATOR).append 12 (signatureValue).toString(); 6 return new String(Base64.encode(nonceValue.getBytes())); } 12 7 public static String md5Hex(String data) { 12 try { 8 MessageDigest digest = MessageDigest.getInstance("MD5"); 12 return new 9 String(Hex.encode(digest.digest(data.getBytes()))); } catch (NoSuchAlgorithmException e) { 13 throw new IllegalStateException("No MD5 algorithm 0 available!"); 13 } 1 13 } } 2 13 3 13 4 13 5 13 6 13 7 13 8 13 9 14 0 14 1 14 2

14 3 14 4 14 5 14 6 14 7 14 8 14 9 15 0 Como se puede ver, el mtodo "calculateNonce()" es el que calcula el valor del token de seguridad que se enviar al formulario Web del cliente. Este valor se calcula por composicin de dos partes y se codifica en Base64. Las dos partes del token son:

Fecha mxima para el login: Clculo con el tiempo actual en milisegundos ms el valor de los segundos definidos como periodo de login Firma del servidor para evitar manipulacin: Se compone de un String con la fecha anteriormente calculada en milisegundos, ms una clave propia del servidor sobre la que se hace un digest en MD5 en formato hexadecimal.

A la hora de recibir el formulario con el intento de autenticacin, lo primero que se hace es validar el timeout con el mtodo "validateTimeout()", donde se recuperar el valor de la fecha mxima para el proceso de login y luego que an no se ha superado. En el mtodo "extractNonceValue(...)" se comprueba que ste parmetro no ha sido manipulado y que est correctamente informado, en caso contrario se lanza la excepcin "BadCredentialsException". Por ltimo, ya solo basta comprobar que no se ha superado el tiempo para el proceso de login, mtodo "isNonceExpired(...)", que en caso de haberse superado se lanza la excepcin "NonceExpiredException". Ya slo nos falta crear el formulario de autenticacin al que le pasaremos el clculo de este token de caducidad. Primero creamos la pgina del formulario: ? 1 2 3 4 5 6 7

<?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> <html xmlns="http://www.w3.org/1999/xhtml" xmlns:h="http://java.sun.com/jsf/html"> <h:head> <meta http-equiv="Content-type" content="text/html; charset=utf-8" /> <title><h:outputText value="Token con caducidad en Spring Security"

8 /></title> 9 </h:head> <h:body> 10 <div id="login"> 11 <form id="loginForm" action="login" method="post"> <input type="hidden" name="username" value="" /> 12 <input type="hidden" name="password" value="" /> 13 <h:inputHidden id="timeout" 14value="#{loginTimeOutView.nonce}"/> 15 <input type="submit" value="Entrar"/> 16 </form> </div> 17 18</h:body>
</html>

Como podis ver en el campo oculto "timeout" hemos metido el valor que nos devuelve el controlador "LoginTimeout" en su mtodo "getNonce(...)". Este ser de la siguiente forma: ? 1 2 package com.autentia.tutoriales; 3 4 import javax.faces.bean.ManagedBean; javax.faces.bean.ManagedProperty; 5 import import javax.faces.bean.RequestScoped; 6 7 @ManagedBean 8 @RequestScoped 9 public class LoginTimeOutView { 10 @ManagedProperty("#{autentiaAuthenticationProvider}") 11 private transient AutentiaAuthenticationProvider 12authenticationProvider; 13 14 public void setAuthenticationProvider( 15 AutentiaAuthenticationProvider authenticationProvider) { this.authenticationProvider = authenticationProvider; 16 } 17 18 public String getNonce(){ 19 return authenticationProvider.calculateNonce(); 20 } 21} 22 Aqu podis ver cmo en este controlador se inyecta el proveedor de autenticacin (AutentiaAuthenticationProvider) para pedirle que genere el token de caducidad que luego l mismo deber conprobar cuando se le enve el formulario.

6. Conclusiones

Bueno, pues con este ejemplo se puede comprobar que gracias a la arquitectura de autenticacin que tiene Spring Security, y a la implementacin por defecto que ya trae, podemos realmente hacer muchas cosas en apenas unos pocos pasos. Como en el ejemplo propuesto, aadiendo un token de caducidad generado en el servidor para el proceso de login. Ya sabes que esto es un ejemplo bsico de lo que podemos hacer, pero espero que os sirva a alguno en vuestros casos particulares. Saludos.

S-ar putea să vă placă și