Login and logout event doesn't fireup in Sprin

2019-09-07 02:15发布

问题:

I have implemented this So I can listen for Login successful event :

public class LoginListener implements ApplicationListener<AuthenticationSuccessEvent> {

@Autowired
UserService us;

public void onApplicationEvent(AuthenticationSuccessEvent event) {

    String userName = ((UserDetails) event.getAuthentication().getPrincipal()).getUsername();          

    System.out.println("lastloginspec : " + userName + " : 00 : " + LocalDateTime.now());

}
}

And this for logout successful event :

@Component
public class LogoutListener implements ApplicationListener<SessionDestroyedEvent> {

@Autowired
UserService us;

@Override
public void onApplicationEvent(SessionDestroyedEvent event)
{
    List<SecurityContext> lstSecurityContext = event.getSecurityContexts();
    UserDetails ud;
    for (SecurityContext securityContext : lstSecurityContext)
    {
        ud = (UserDetails) securityContext.getAuthentication().getPrincipal();

        us.findAllUsersByEmail(ud.getUsername()).get(0).setLastLogout(LocalDateTime.now());
        System.out.println("lastloginspec : " + ud.getUsername() + " : 00 : " + LocalDateTime.now());
    }
}

}

but can't see any event being firedup.

EDIT :

this is my success Handler :

public class mySuccessfulAuthenticationHandler implements AuthenticationSuccessHandler {

protected Log logger = LogFactory.getLog(this.getClass());
    private RedirectStrategy redirectStrategy = new DefaultRedirectStrategy();

    @Override
    public void onAuthenticationSuccess(HttpServletRequest request, 
      HttpServletResponse response, Authentication authentication) throws IOException {
        handle(request, response, authentication);
        clearAuthenticationAttributes(request);
    }

    protected void handle(HttpServletRequest request, 
      HttpServletResponse response, Authentication authentication) throws IOException {
        String targetUrl = "/";

        if (response.isCommitted()) {
            logger.debug("Response has already been committed. Unable to redirect to " + targetUrl);
            return;
        }

        redirectStrategy.sendRedirect(request, response, targetUrl);
    }


    protected void clearAuthenticationAttributes(HttpServletRequest request) {
        HttpSession session = request.getSession(false);
        if (session == null) {
            return;
        }
        session.removeAttribute(WebAttributes.AUTHENTICATION_EXCEPTION);
    }

    public void setRedirectStrategy(RedirectStrategy redirectStrategy) {
        this.redirectStrategy = redirectStrategy;
    }
    protected RedirectStrategy getRedirectStrategy() {
        return redirectStrategy;
    }

}

EDIT 2 :

here's my config :

@Autowired
public void configureGlobal(AuthenticationManagerBuilder auth) throws Exception {
  auth.userDetailsService(userDetailsService);

}


@Override
protected void configure(HttpSecurity http) throws Exception {

  http.csrf().disable()
      .authorizeRequests()
         .antMatchers("/login", "/logout").permitAll()
         .antMatchers("/resources/**").permitAll()
         .antMatchers("/Project/**").hasAnyAuthority("COLLABORATOR","CHEF","SUPERCHEF")
         .antMatchers("/User/**").hasAnyAuthority("COLLABORATOR","CHEF","SUPERCHEF")
         .antMatchers("/Reunion/**").hasAnyAuthority("COLLABORATOR","CHEF","SUPERCHEF")
         .antMatchers("/Task/**").hasAnyAuthority("COLLABORATOR","CHEF","SUPERCHEF")
         .anyRequest().authenticated()
        .and().formLogin()
                .loginPage("/login")
                .defaultSuccessUrl("/")
                .successHandler(authenticationSuccessHandler)
                .permitAll()
        .and().logout().logoutSuccessUrl("/login").permitAll()
        .and().sessionManagement().maximumSessions(1).sessionRegistry(sessionRegistry());


}


@Bean
public SessionRegistry sessionRegistry() {

    return new SessionRegistryImpl();
}

EDIT 3 :

In my WebConfig :

@Bean
public HttpSessionEventPublisher httpSessionEventPublisher() {
    return new HttpSessionEventPublisher();
}

EDIT 4 :

I've tried these solution :

using @EventListener from Spring 4.2

Adding my classes as beans in my webConfig and register them as listener in servletContext.addListener(new LoginListener())

Any help will be appreciated. thank you.

回答1:

You have to add the HttpSessionEventPublisher to the ServletContext.

For web applications with web.xml, see HttpSessionEventPublisher:

Declared in web.xml as

<listener>
    <listener-class>org.springframework.security.web.session.HttpSessionEventPublisher</listener-class>
</listener>

Publishes HttpSessionApplicationEvents to the Spring Root WebApplicationContext. Maps javax.servlet.http.HttpSessionListener.sessionCreated() to ?HttpSessionCreatedEvent. Maps javax.servlet.http.HttpSessionListener.sessionDestroyed() to HttpSessionDestroyedEvent.

For web applications without web.xml, see ServletContext.html#addListener:

Adds the given listener to this ServletContext.

The given listener must be an instance of one or more of the following interfaces:

  • ServletContextAttributeListener
  • ServletRequestListener
  • ServletRequestAttributeListener
  • HttpSessionListener
  • HttpSessionAttributeListener