¿A que denominamos Account Lockout?
Lockout es el nombre del mecanismo mediante el cual se bloquea la cuenta de un usuario luego de intentar varias veces sin éxito el inicio de sesión en un sistema determinado.
El bloqueo de las cuentas se realiza para evitar los ataques de agentes mal intencionados que pretenden inferir la contraseña de un usuario por diversos mecanismos, como fuerza bruta, ingeniería social, etc.
Acerca de ala implementación utilizando Spring
Spring Security permite extender el comportamiento de uno de sus filtros (AuthenticationProcessingFilter) de forma que se pueda hacer uso de los métodos onSuccesfullAuthentication() y onUnSuccesfullAuthentication().
Para bloquear la cuenta de un usuario, tras una cantidad determinada de intentos erroneos de login, se deben seguir los siguientes pasos:
- Crear una clase CustomAuthProcFilter que extienda de AuthenticationProcessingFilter.
- Agregar en la clase correspondiente a los usuarios la propiedad failedLoginAttempts, en la misma se almacenará el número de intentos de login erroneos. Este contador se irá incrementando por cada login erróneo y se volverá a cero por cada inicio de sesión exitoso.
- Dado que la clase correspondiente a los usuarios debe extender la clase UserDetails, la misma deberá contener el método isAccountNonLocked(), en caso de haber llegado a la máxima cantidad permitida de intentos de login, este método tendrá que retornar false.
Cuando el método isAccountNonLocked() retorna false, Spring Security se encarga de lanzar una excepcion por usuario bloqueado.
Cambios en la configuración del applicationContext
El CustomAuthProcFilter, como se ha dicho anteriormente reemplazará al AuthenticationProcessingFilter, por lo que deberá declararse con ese id en el applicationContext:
<beans:bean id="authenticationProcessingFilter" class="com.springsecuritypoc.web.CustomAuthProcFilter"> <custom-filter position="AUTHENTICATION_PROCESSING_FILTER" /> <beans:property name="defaultTargetUrl" value="/main.jsp" /> <beans:property name="authenticationManager" ref="authenticationManager" /> <beans:property name="authenticationFailureUrl" value="/index.jsp? authfailed=true" /> <beans:property name="userManager" ref="userManager" /> </beans:bean>
Se debe tener en cuenta que la configuración del filtro reemplaza el elemento <form-login> declarado dentro de <http>, por ello será necesario remover la siguiente declaración:
<form-login login-page="/jsp/login.jsp" authentication-failure-url="/jsp/login.jsp?login_error=1" default-target-url="/jsp/index.jsp"/>
Métodos de la clase CustomAuthProcessingFilter
A continuación se muestran la implementación de los métodos onSuccessfulAuthentication y onUnsuccessfulAuthenticationde la clase correspondiente al filtro modificado:
@Override protected void onSuccessfulAuthentication(HttpServletRequest request, HttpServletResponse response, Authentication authResult) throws IOException { super.onSuccessfulAuthentication(request, response, authResult); request.getUserPrincipal(); String authName = authResult.getName(); User userError = userManager.getUserByUsername(authName); .... } @Override protected void onUnsuccessfulAuthentication(HttpServletRequest request, HttpServletResponse response, AuthenticationException failed) { try { super.onUnsuccessfulAuthentication(request, response, failed); String authName = failed.getAuthentication().getName(); User userError = userManager.getUserByUsername(authName); .... }
Diagramas de secuencia
A continuación se incluyen dos diagramas que capturan las secuencias de logien exitoso y login fallido.
Secuencia de un inicio de sesión exitoso
Secuencia de un inicio de sesión fallido
