2011-12-30 10 views
18

Estamos usando spring security 3.0.5, Java 1.6 y Tomcat 6.0.32. En nuestro archivo de configuración .xml tenemos:¿Cómo puedo obtener el nombre de usuario de un inicio de sesión fallido utilizando la seguridad de primavera?

<form-login login-page="/index.html" default-target-url="/postSignin.html" always-use-default-target="true" 
authentication-failure-handler-ref="authenticationFailureHandler"/> 

y nuestra authenticationFailureHandler define como:

<beans:bean id="authenticationFailureHandler" class="org.springframework.security.web.authentication.ExceptionMappingAuthenticationFailureHandler"> 
    <beans:property name="exceptionMappings"> 
     <beans:props> 
    <beans:prop key="org.springframework.security.authentication.BadCredentialsException">/index.html?authenticationFailure=true</beans:prop> 
    </beans:props> 
    </beans:property> 
</beans:bean> 

Java

@RequestMapping(params={"authenticationFailure=true"}, value ="/index.html") 
    public String handleInvalidLogin(HttpServletRequest request) { 
     //... How can I get the username that was used??? 
     // I've tried: 
     Object username = request.getAttribute("SPRING_SECURITY_LAST_USERNAME_KEY"); 
     Object username = request.getAttribute("SPRING_SECURITY_LAST_USERNAME"); // deprecated 
    } 

Así que estamos dirigiendo toda BadCredentialsExceptions a la index.html y IndexController. En el IndexController me gustaría obtener el username que se utilizó para el intento fallido de inicio de sesión. ¿Cómo puedo hacer esto?

Respuesta

20

De acuerdo, la respuesta resultó ser algo extremadamente simple, sin embargo, hasta donde sé, no muy discutido ni documentado.

Aquí es todo lo que tenía que hacer (no hay configuraciones en cualquier lugar que acaba de crear esta clase) ...

import org.apache.log4j.Logger; 
import org.springframework.context.ApplicationListener; 
import org.springframework.security.authentication.event.AuthenticationFailureBadCredentialsEvent; 
import org.springframework.stereotype.Component; 

@Component 
public class MyApplicationListener implements ApplicationListener<AuthenticationFailureBadCredentialsEvent> { 
    private static final Logger LOG = Logger.getLogger(MyApplicationListener.class); 

    @Override 
    public void onApplicationEvent(AuthenticationFailureBadCredentialsEvent event) { 
     Object userName = event.getAuthentication().getPrincipal(); 
     Object credentials = event.getAuthentication().getCredentials(); 
     LOG.debug("Failed login using USERNAME [" + userName + "]"); 
     LOG.debug("Failed login using PASSWORD [" + credentials + "]"); 
    } 
} 

Estoy lejos de ser un experto en seguridad de primavera así que si alguien lee esto y sabe de una razón por la que shouldn No lo hagas así o conoces una mejor manera en la que me encantaría escuchar al respecto.

+0

Lo intenté pero no funciona –

+0

Tenemos este código exacto trabajando en nuestra configuración. No puedo decirte por qué no funcionaría en el tuyo. No tuvimos que configurar nada nuevo ni cambiar ningún archivo .xml en ninguna parte. Las anotaciones parecen apuntar a este código y ejecutarlo cuando hay un inicio de sesión incorrecto. Funciona perfectamente para nosotros. – kasdega

+0

tal vez requiera alguna otra configuración. Por cierto, he encontrado una solución alternativa. Gracias por la información, aunque :) –

5

En su lugar, podría suministrar su propia versión de DefaultAuthenticationEventPublisher y anular el método publishAuthenticationFailure.

+0

¿Tiene un ejemplo de esto que puede indicarme? – kasdega

+1

Tendría que conectar en la implementación de su propietario. Vea si puede extender DefaultAuthenticationEventPublisher. Luego, conéctelo al ProviderManager (que es una implementación de AuthenticationManager, que debe haber declarado en Spring Security). Esa clase tiene un método setAuthenticationEventPublisher. – Saish

1

He encontrado que esto funciona para mí. Por desgracia, todavía no pareció que la ubicación exacta de esta en los documentos SpringSecurity:

En cualquier acción, se puede comprobar el utilizado por última vez nombre de usuario (no importa lo que se falló el inicio de sesión o no):

String username = (String) request.getSession().getAttribute("SPRING_SECURITY_LAST_USERNAME"); 
+1

UsernamePasswordAuthenticationFilter.SPRING_SECURITY_LAST_USERNAME_KEY es la constante que corresponde al nombre del atributo. Ahora está en desuso. – mrbaboo

+0

@mrbaboo: así que es por eso que no puedo encontrar nada acerca de esta constante. Por lo tanto, está en desuso, ¿conoce alguna forma alternativa de lograr el mismo efecto? –

+2

Solo quería señalar que el código que almacenaba este valor en desuso en la sesión se eliminó en la versión 3.1.0 de Spring Security. Tendrá que utilizar uno de los otros métodos descritos anteriormente si desea lograr este efecto con versiones recientes. – Jules

10

lo hice de esta manera:

  1. creado una clase que se extiende SimpleUrlAuthenticationFailureHandler

  2. OVERRID el método onAuthenticationFailure, WH Ich recibe un HttpServletRequest como parámetro.

  3. request.getParameter("username"), donde "username" es el nombre de mi entrada en mi formulario HTML.

+1

Funciona bien, solo un comentario, si está utilizando el nombre predeterminado en el formulario para el texto de entrada que es ** j_nombre de usuario **, debe capturarlo así. 'request.getParameter (" j_username ")'. – OJVM

1

no parece que haya mucha información sobre esta solución, pero si establece failureForwardUrl en la configuración de la primavera de Seguridad, se le dirigirá a la página de error en lugar de redirigir. A continuación, puede recuperar fácilmente el nombre de usuario y la contraseña. Por ejemplo, en su configuración añadir: .and().formLogin().failureForwardUrl("/login/failed") (* url debe ser diferente de la página de acceso URL)

Y en el controlador de inicio de sesión, los siguientes:

@RequestMapping(value = "/login/failed") 
public String loginfailed(@ModelAttribute(UsernamePasswordAuthenticationFilter.SPRING_SECURITY_FORM_USERNAME_KEY) String user, @ModelAttribute(UsernamePasswordAuthenticationFilter.SPRING_SECURITY_FORM_PASSWORD_KEY) String password) { 
    // Your code here 
} 

SPRING_SECURITY_FORM_USERNAME_KEY, SPRING_SECURITY_FORM_PASSWORD_KEY son los nombres predeterminados , pero también puede configurarlos en el FormLoginConfigurer:

.and().formLogin().usernameParameter("email").passwordParameter("password").failureForwardUrl("/login/failed") 
Cuestiones relacionadas