I\'d like to track when users are logging in to my application. I have some code that I would like to execute right after the user is authenticated. The problem is, I can\'t fig
If you want to avoid reading all the thread : curated version with annotations & a bit more explanatory :
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");
}
}
Just write your own SpringSecurityFilter and add it to the filter chain right after your authentication provider is called.
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}
}
}
Then in your configuration XML (wherever you setup the Security Filter chain) add a line like this:
<bean id="auditFilter" class="my.code.AuditFilter>
<security:custom-filter position="LAST"/> <-- you can change the position
</bean>
probably will be usefull for someone... In case of Spring 3, configure security:
<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"/>
and implement an appropriate class:
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());
}
}
You can link resources via that xml config.
In case you want to continue with default behavior but just in between perform your own business logic, you may extend SimpleUrlAuthenticationSuccessHandler
and invoke super.onAuthenticationSuccess(request, response, authentication);
before you return. More details refer to https://stackoverflow.com/a/6770785/418439
Authentication does not necessarily imply successful login. A user can be successfully authenticated via, e.g., two-way SSL (X.509 certs), and still Spring Security will redirect you to an error page if session concurrency management is set up with max-sessions="1"
and this is a second concurrent login attempt. If your setup is simple, without session concurrency control, you can assume login = authentication for all practical purposes. Otherwise, if you have, e.g., logic that records every successful login in a database, you will have to invoke this logic at the point of actual login, not at the point of authentication. One way (by no means optimal, subject to my limited understanding of the Spring Security framework) to do this is to implement your own ConcurrentSessionControlAuthenticationStrategy
(click here for the source code) and inject it into CompositeSessionAuthenticationStrategy
in your Spring Security (3.2 and above) configuration XML:
<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"/>
I would have preferred to inject a custom PostLogin
handler into the framework's ConcurrentSessionControlAuthenticationStrategy
, instead of copy-pasting from it into my custom ConcurrentSessionControlAuthenticationStrategy
and making modifications to it, but I do not know of a way to do this at the moment.
A more complete configuration example can be found here.
This link Post Authentication Logic on ByteClip explains how to execute some logic after successful authentication without disturbing spring security filter chain