简体   繁体   中英

How to listen for login/logout events using Spring Security in a Spring Boot application?

I am trying to log messages after a successful/failed login/logout in Spring Security.

Also, I'm using Spring Boot, so there is little configuration code.

The form that I am using is auto-generated.

WebSecurityConfig.java

@Configuration
@EnableWebSecurity
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {

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

        http
            .authorizeRequests()
                .antMatchers("/resources/**").permitAll()
                .anyRequest().fullyAuthenticated()
                .and()
            .formLogin();

    }

    @Configuration
    protected static class AuthenticationConfiguration extends GlobalAuthenticationConfigurerAdapter {

        @Override
        public void init(AuthenticationManagerBuilder auth) throws Exception {
            auth
                .ldapAuthentication()
                .userSearchFilter("(uid={0})")
                .contextSource()
                .url("ldap://...:389/ou=...,dc=...,dc=...")
                .managerDn("cn=...,dc=...,dc=...")
                .managerPassword("...");
        }
    }
}

logback.xml

<?xml version="1.0" encoding="UTF-8"?>
<configuration>
    <include resource="org/springframework/boot/logging/logback/base.xml"/>
</configuration>

My code for login success is as follows:

LoginSuccessService.java

import java.util.Date;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.context.ApplicationListener;
import org.springframework.security.authentication.event.*;
import org.springframework.stereotype.Component;
import org.springframework.stereotype.Service;

@Component
public class LoginSuccessService implements ApplicationListener<InteractiveAuthenticationSuccessEvent>{

    private static final Logger logger = LoggerFactory.getLogger(LoginSuccessService.class);

    @Override
    public void onApplicationEvent(InteractiveAuthenticationSuccessEvent event) {
        logger.debug("You have been logged in successfully.");
        Date loginDate = new Date();
        logger.debug("Login Time: " + loginDate.toString());
    }
}

It won't work. I get nothing in the log.

What additional code do I need to write, if any? Do I need to initialize this listener anywhere?

I also used this link as reference, but I figured I didn't need to write a publisher, as I am not writing my own class for the event.

I have also tried with AuthenticationSuccessEvent instead of InteractiveAuthenticationSuccessEvent , but same thing.

If it helps, a failed login produces the following output(expected output should include "Failed to log in" and the current date, this is a log with debug=TRUE in application.properties ):

2016-03-16 18:50:12.779 DEBUG 8895 --- [nio-8080-exec-7] o.s.b.c.web.OrderedRequestContextFilter  : Bound request context to thread: org.apache.catalina.connector.RequestFacade@67a404ea
2016-03-16 18:50:12.779 DEBUG 8895 --- [nio-8080-exec-7] o.s.security.web.FilterChainProxy        : /login at position 1 of 13 in additional filter chain; firing Filter: 'WebAsyncManagerIntegrationFilter'
2016-03-16 18:50:12.779 DEBUG 8895 --- [nio-8080-exec-7] o.s.security.web.FilterChainProxy        : /login at position 2 of 13 in additional filter chain; firing Filter: 'SecurityContextPersistenceFilter'
2016-03-16 18:50:12.779 DEBUG 8895 --- [nio-8080-exec-7] w.c.HttpSessionSecurityContextRepository : Obtained a valid SecurityContext from SPRING_SECURITY_CONTEXT: 'org.springframework.security.core.context.SecurityContextImpl@56979972: Authentication: org.springframework.security.authentication.UsernamePasswordAuthenticationToken@56979972: Principal: org.springframework.security.ldap.userdetails.LdapUserDetailsImpl@a96aab26: Dn: cn=User,ou=users,dc=vs,dc=local; Username: user; Password: [PROTECTED]; Enabled: true; AccountNonExpired: true; CredentialsNonExpired: true; AccountNonLocked: true; Not granted any authorities; Credentials: [PROTECTED]; Authenticated: true; Details: org.springframework.security.web.authentication.WebAuthenticationDetails@2cd90: RemoteIpAddress: 0:0:0:0:0:0:0:1; SessionId: 524F4F9744824535095B43C18FBA71F4; Not granted any authorities'
2016-03-16 18:50:12.780 DEBUG 8895 --- [nio-8080-exec-7] o.s.security.web.FilterChainProxy        : /login at position 3 of 13 in additional filter chain; firing Filter: 'HeaderWriterFilter'
2016-03-16 18:50:12.780 DEBUG 8895 --- [nio-8080-exec-7] o.s.s.w.header.writers.HstsHeaderWriter  : Not injecting HSTS header since it did not match the requestMatcher org.springframework.security.web.header.writers.HstsHeaderWriter$SecureRequestMatcher@3a3c5471
2016-03-16 18:50:12.780 DEBUG 8895 --- [nio-8080-exec-7] o.s.security.web.FilterChainProxy        : /login at position 4 of 13 in additional filter chain; firing Filter: 'CsrfFilter'
2016-03-16 18:50:12.780 DEBUG 8895 --- [nio-8080-exec-7] o.s.security.web.FilterChainProxy        : /login at position 5 of 13 in additional filter chain; firing Filter: 'LogoutFilter'
2016-03-16 18:50:12.780 DEBUG 8895 --- [nio-8080-exec-7] o.s.s.w.u.matcher.AntPathRequestMatcher  : Checking match of request : '/login'; against '/logout'
2016-03-16 18:50:12.780 DEBUG 8895 --- [nio-8080-exec-7] o.s.security.web.FilterChainProxy        : /login at position 6 of 13 in additional filter chain; firing Filter: 'UsernamePasswordAuthenticationFilter'
2016-03-16 18:50:12.780 DEBUG 8895 --- [nio-8080-exec-7] o.s.s.w.u.matcher.AntPathRequestMatcher  : Checking match of request : '/login'; against '/login'
2016-03-16 18:50:12.780 DEBUG 8895 --- [nio-8080-exec-7] w.a.UsernamePasswordAuthenticationFilter : Request is to process authentication
2016-03-16 18:50:12.780 DEBUG 8895 --- [nio-8080-exec-7] o.s.s.authentication.ProviderManager     : Authentication attempt using org.springframework.security.ldap.authentication.LdapAuthenticationProvider
2016-03-16 18:50:12.780 DEBUG 8895 --- [nio-8080-exec-7] o.s.s.l.a.LdapAuthenticationProvider     : Processing authentication request for user: iprnein
2016-03-16 18:50:12.780 DEBUG 8895 --- [nio-8080-exec-7] o.s.s.l.s.FilterBasedLdapUserSearch      : Searching for user 'iprnein', with user search [ searchFilter: '(uid={0})', searchBase: '', scope: subtree, searchTimeLimit: 0, derefLinkFlag: false ]
2016-03-16 18:50:12.781 DEBUG 8895 --- [nio-8080-exec-7] o.s.l.c.support.AbstractContextSource    : Got Ldap context on server 'ldap://192.168.10.41:389/ou=users,dc=vs,dc=local'
2016-03-16 18:50:12.788 DEBUG 8895 --- [nio-8080-exec-7] o.s.s.ldap.SpringSecurityLdapTemplate    : Searching for entry under DN 'ou=users,dc=vs,dc=local', base = '', filter = '(uid={0})'
2016-03-16 18:50:12.789 DEBUG 8895 --- [nio-8080-exec-7] o.s.b.f.s.DefaultListableBeanFactory     : Returning cached instance of singleton bean 'loginFailureService'
2016-03-16 18:50:12.790 DEBUG 8895 --- [nio-8080-exec-7] o.s.b.f.s.DefaultListableBeanFactory     : Returning cached instance of singleton bean 'delegatingApplicationListener'
2016-03-16 18:50:12.790 DEBUG 8895 --- [nio-8080-exec-7] w.a.UsernamePasswordAuthenticationFilter : Authentication request failed: org.springframework.security.authentication.BadCredentialsException: Bad credentials
2016-03-16 18:50:12.790 DEBUG 8895 --- [nio-8080-exec-7] w.a.UsernamePasswordAuthenticationFilter : Updated SecurityContextHolder to contain null Authentication
2016-03-16 18:50:12.790 DEBUG 8895 --- [nio-8080-exec-7] w.a.UsernamePasswordAuthenticationFilter : Delegating to authentication failure handler org.springframework.security.web.authentication.SimpleUrlAuthenticationFailureHandler@19d8353
2016-03-16 18:50:12.790 DEBUG 8895 --- [nio-8080-exec-7] .a.SimpleUrlAuthenticationFailureHandler : Redirecting to /login?error
2016-03-16 18:50:12.790 DEBUG 8895 --- [nio-8080-exec-7] o.s.s.web.DefaultRedirectStrategy        : Redirecting to '/login?error'
2016-03-16 18:50:12.790 DEBUG 8895 --- [nio-8080-exec-7] w.c.HttpSessionSecurityContextRepository : SecurityContext is empty or contents are anonymous - context will not be stored in HttpSession.
2016-03-16 18:50:12.790 DEBUG 8895 --- [nio-8080-exec-7] s.s.w.c.SecurityContextPersistenceFilter : SecurityContextHolder now cleared, as request processing completed
2016-03-16 18:50:12.790 DEBUG 8895 --- [nio-8080-exec-7] o.s.b.c.web.OrderedRequestContextFilter  : Cleared thread-bound request context: org.apache.catalina.connector.RequestFacade@67a404ea
2016-03-16 18:50:12.800 DEBUG 8895 --- [nio-8080-exec-9] o.s.b.c.web.OrderedRequestContextFilter  : Bound request context to thread: org.apache.catalina.connector.RequestFacade@67a404ea
2016-03-16 18:50:12.800 DEBUG 8895 --- [nio-8080-exec-9] o.s.security.web.FilterChainProxy        : /login?error at position 1 of 13 in additional filter chain; firing Filter: 'WebAsyncManagerIntegrationFilter'
2016-03-16 18:50:12.800 DEBUG 8895 --- [nio-8080-exec-9] o.s.security.web.FilterChainProxy        : /login?error at position 2 of 13 in additional filter chain; firing Filter: 'SecurityContextPersistenceFilter'
2016-03-16 18:50:12.800 DEBUG 8895 --- [nio-8080-exec-9] w.c.HttpSessionSecurityContextRepository : HttpSession returned null object for SPRING_SECURITY_CONTEXT
2016-03-16 18:50:12.800 DEBUG 8895 --- [nio-8080-exec-9] w.c.HttpSessionSecurityContextRepository : No SecurityContext was available from the HttpSession: org.apache.catalina.session.StandardSessionFacade@68e82290. A new one will be created.
2016-03-16 18:50:12.800 DEBUG 8895 --- [nio-8080-exec-9] o.s.security.web.FilterChainProxy        : /login?error at position 3 of 13 in additional filter chain; firing Filter: 'HeaderWriterFilter'
2016-03-16 18:50:12.800 DEBUG 8895 --- [nio-8080-exec-9] o.s.s.w.header.writers.HstsHeaderWriter  : Not injecting HSTS header since it did not match the requestMatcher org.springframework.security.web.header.writers.HstsHeaderWriter$SecureRequestMatcher@3a3c5471
2016-03-16 18:50:12.800 DEBUG 8895 --- [nio-8080-exec-9] o.s.security.web.FilterChainProxy        : /login?error at position 4 of 13 in additional filter chain; firing Filter: 'CsrfFilter'
2016-03-16 18:50:12.800 DEBUG 8895 --- [nio-8080-exec-9] o.s.security.web.FilterChainProxy        : /login?error at position 5 of 13 in additional filter chain; firing Filter: 'LogoutFilter'
2016-03-16 18:50:12.800 DEBUG 8895 --- [nio-8080-exec-9] o.s.s.w.u.matcher.AntPathRequestMatcher  : Request 'GET /login' doesn't match 'POST /logout
2016-03-16 18:50:12.800 DEBUG 8895 --- [nio-8080-exec-9] o.s.security.web.FilterChainProxy        : /login?error at position 6 of 13 in additional filter chain; firing Filter: 'UsernamePasswordAuthenticationFilter'
2016-03-16 18:50:12.800 DEBUG 8895 --- [nio-8080-exec-9] o.s.s.w.u.matcher.AntPathRequestMatcher  : Request 'GET /login' doesn't match 'POST /login
2016-03-16 18:50:12.800 DEBUG 8895 --- [nio-8080-exec-9] o.s.security.web.FilterChainProxy        : /login?error at position 7 of 13 in additional filter chain; firing Filter: 'DefaultLoginPageGeneratingFilter'
2016-03-16 18:50:12.801 DEBUG 8895 --- [nio-8080-exec-9] w.c.HttpSessionSecurityContextRepository : SecurityContext is empty or contents are anonymous - context will not be stored in HttpSession.
2016-03-16 18:50:12.801 DEBUG 8895 --- [nio-8080-exec-9] s.s.w.c.SecurityContextPersistenceFilter : SecurityContextHolder now cleared, as request processing completed
2016-03-16 18:50:12.801 DEBUG 8895 --- [nio-8080-exec-9] o.s.b.c.web.OrderedRequestContextFilter  : Cleared thread-bound request context: org.apache.catalina.connector.RequestFacade@67a404ea

The error turned out to be configuration-related.

For capturing login events, I used the objects

InteractiveAuthenticationSuccessEvent or AuthenticationSuccessEvent (logout doesn't have an implemented listener yet, you might have luck with HttpSessionEvent ).

Also, it's important to see whether or not the logger is configured to log your package; the application is not configured by default to log application messages. That is why I was not getting any output.

So, two things:

  • If your package name is com.mycompany , you should add a line in your application.properties or application.yml file(usually found in <PROJ_DIR>/src/main/resources/ ; if not, create your own) for logging:

application.properties :

logging.level.com.mycompany=DEBUG/INFO/WARN/ERROR 
    #debug is lowest, error is highest

or:

application.yml :

logging:
    level:
        com:
            mycompany: DEBUG/INFO/WARN/ERROR
  • If you are trying to log an outside package, log it with the debug() method or it might not show up(I used info() and I got nothing).

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM