2010-04-05 9 views
19

me gustaría hacer un seguimiento cuando los usuarios inician sesión en que mi solicitud. Tengo un código que me gustaría ejecutar justo después de que el usuario se haya autenticado. El problema es que no puedo entender a dónde llamarlo. ¿La seguridad de primavera tiene una forma de llamar a un método después de la autenticación?Primavera-Seguridad: Método de llamadas después de la autenticación

Respuesta

4

Sólo tiene que escribir su propio SpringSecurityFilter y añadirlo a la cadena de filtros inmediatamente después de su proveedor de autenticación se llama.

package my.code; 

public class AuditFilter extends SpringSecurityFilter { 

    public void doFilterHttp(...) throws ... { 
     {application code to run before request is processed} 
     chain.doFilter(...); 
     {application code to run after request has fully processed} 
    } 
} 

Luego, en su configuración XML (donde quiera que la configuración de la cadena de filtro de seguridad) añadir una línea como esta:

<bean id="auditFilter" class="my.code.AuditFilter> 
    <security:custom-filter position="LAST"/> <-- you can change the position 
</bean> 
+0

Tenga en cuenta que SpringSecurityFilter cambiado a los genéricos GenericFilterBean web de primavera en la primavera de Seguridad 3. –

-1

Este enlace Post Authentication Logic en ByteClip explica cómo ejecutar alguna lógica después de la autenticación exitosa sin molestar Spring Security cadena de filtros

+2

enlace roto. ... – chrismarx

11

mejor forma de hacerlo es crear un detector de aplicación y registrarlo en el contexto de seguridad de la primavera.

import org.springframework.context.ApplicationListener; 
import org.springframework.security.authentication.event.InteractiveAuthenticationSuccessEvent; 

public class AuthenticationSuccessListener implements ApplicationListener<InteractiveAuthenticationSuccessEvent> { 

    @Override 
    public void onApplicationEvent(InteractiveAuthenticationSuccessEvent event) { 
     System.out.println("User Logged In"); 

    } 
} 

Asegúrese de agregar a la clase anterior el spring-security.xml como un bean. Hay muchos otros tipos de escuchas de eventos de seguridad que puede escuchar, consulte la jerarquía de tipos para obtener una lista de todos los tipos de eventos de seguridad que puede escuchar.

+0

Dependiendo de la situación, pero ese suele ser mi camino por recorrer. Si necesita crear un efecto secundario del evento de autenticación, use ApplicationListener. Si necesita especificar cómo se debe manejar el proceso de autenticación use los controladores. En este caso, "seguimiento de la acción de autenticación", iría para el evento y se parecería más a un efecto secundario. – wooki

30

probablemente será muy útil para alguien ... En caso de primavera 3, configurar la seguridad:

<security:http use-expressions="true" auto-config="true"> 
    <security:intercept-url pattern="..."/> 
    <security:form-login 
      authentication-failure-handler-ref="authFailureHandler" 
      authentication-success-handler-ref="authSuccessHandler"/> 
    <security:logout success-handler-ref="logoutSuccessHandler" 
      invalidate-session="true"/> 
    <security:session-management session-fixation-protection="newSession"/> 
</security:http> 

<bean id="authFailureHandler" class="mine.AuthenticationFailureHandlerImpl"/> 
<bean id="authSuccessHandler" class="mine.AuthenticationSuccessHandlerImpl"/> 
<bean id="logoutSuccessHandler" class="mine.LogoutSuccessHandlerImpl"/> 

e implementar una clase apropiada:

public class AuthenticationSuccessHandlerImpl implements AuthenticationSuccessHandler { 

    @Override 
    public void onAuthenticationSuccess(HttpServletRequest request, HttpServletResponse response, Authentication authentication) throws IOException, ServletException { 
     //do what you want with 
     response.getOutputStream().write("success".getBytes()); 
    } 
} 

puede vincular los recursos a través de ese xml config.

+1

¡Buenas cosas! Gracias por la autenticación-éxito-controlador-ref –

+0

Si quiero agregar una pequeña acción y luego continuar con el manejo normal, ¿cómo sería? – DiegoSahagun

6

En caso de que desee continuar con el comportamiento predeterminado, pero en el medio realice su propia lógica comercial, puede extend SimpleUrlAuthenticationSuccessHandler e invocar super.onAuthenticationSuccess(request, response, authentication); antes de regresar. Más detalles se refieren a https://stackoverflow.com/a/6770785/418439

+0

Esto es lo que suelo hacer y recomiendo hacerlo también si no necesita cambiar nada en la implementación original, sino simplemente requiere una funcionalidad adicional. Creo un ChainAuthenticationSuccessHandler que luego llamará a mi controlador personalizado y a uno de los manejadores existentes como 'SimpleUrlAuthenticationSuccessHandler'. Lo encuentro más confiable y limpio que extender la clase de Spring. Supongo que también podrías crear algún tipo de clase de decorador sobre el controlador original para evitar la herencia, pero la solución de cadena me resulta más atractiva. – wooki

1

Autenticación hace no implica necesariamente un inicio de sesión exitoso. Un usuario puede ser autenticado con éxito a través de, por ejemplo, SSL de dos vías (certs X.509), y aún la primavera de Seguridad que se redirigir a una página de error si la gestión de sesiones concurrencia está configurado con max-sessions="1" y esto es un segundo intento de acceso concurrente. Si su configuración es simple, sin control de concurrencia de sesión, puede asumir login = authentication para todos los propósitos prácticos. De lo contrario, si tiene, por ejemplo, la lógica que registra cada éxito de inicio de sesión en una base de datos, tendrá que invocar esta lógica en el punto de inicio de sesión real, no en el punto de autenticación. Una forma (de ninguna manera óptima, sujeta a mi limitada comprensión del marco Spring Security) para hacer esto es poner en práctica su propio ConcurrentSessionControlAuthenticationStrategy (clic here para el código fuente) y lo inyecta en CompositeSessionAuthenticationStrategy en su Spring Security (3.2 y superiores) XML de configuración:

<http> 
    . 
    . 
    <session-management session-authentication-strategy-ref="sas" /> 
    . 
    . 
</http> 
. 
. 
<beans:bean id="sas" class="org.springframework.security.web.authentication.session.CompositeSessionAuthenticationStrategy"> 
    <beans:constructor-arg> 
     <beans:list> 
      <beans:bean class="path.to.my.implementation.of.ConcurrentSessionControlAuthenticationStrategy"> 
       <beans:constructor-arg ref="sessionRegistry"/> 
       <beans:property name="maximumSessions" value="1"/> 
       <beans:property name="exceptionIfMaximumExceeded" value="true"/> 
      <beans:bean> 
      <beans:bean class="org.springframework.security.web.authentication.session.SessionFixationProtectionStrategy"/> 
      <beans:bean class="org.springframework.security.web.authentication.session.RegisterSessionAuthenticationStrategy"/> 
       <beans:constructor-arg ref="sessionRegistry"/> 
      </beans:bean> 
     </beans:list> 
    </beans:constructor-arg> 
</beans:bean> 

<beans:bean id="sessionRegistry" class="org.springframework.security.core.session.SessionRegistryImpl"/> 

yo hubiera preferido para inyectar un controlador personalizado PostLogin en el marco de ConcurrentSessionControlAuthenticationStrategy, en lugar de copiar y pegar de él en mi costumbre ConcurrentSessionControlAuthenticationStrategy y hacer modificaciones en él, pero no sé de una manera para hacer esto en este momento.

Se puede encontrar un ejemplo de configuración más completo here.

2

Si se quiere evitar la lectura de toda la rosca: Versión curada con anotaciones & un poco más explicativas:

import org.springframework.context.ApplicationListener; 
import org.springframework.security.authentication.event.AuthenticationSuccessEvent; 
import org.springframework.security.core.userdetails.User; 
import org.springframework.stereotype.Component; 

@Component 
public class LoginSuccessListener implements ApplicationListener<AuthenticationSuccessEvent{ 

    @Override 
    public void onApplicationEvent(AuthenticationSuccessEvent evt) { 

     // if you just need the login 
     String login = evt.getAuthentication().getName(); 
     System.out.println(login + " has just logged in"); 

     // if you need to access full user (ie only roles are interesting -- the rest is already verified as login is successful) 
     User user = (User) evt.getAuthentication().getPrincipal(); 
     System.out.println(user.getUsername() + " has just logged in"); 

    } 
} 
Cuestiones relacionadas