Custom AuthenticationProcessingFilter for spring security to perform actions on login
Question like this one popup on the spring security forum all the time. The question is almost always the same. The system must perform some custom action after a user logs in or out of the system. And almost always this action has to be performed on the session like setting an attribute or removing one. Sometimes user’s also want to put their own User object in the session for later use in the application. All these actions can be performed by writing a custom AuthenticationProcessingFilter and replacing the default instance on the filter chain with your implementation.
Before I show you how to write your very own filter, let me just say that you don’t necessarily need to do all this work just to put your user’s details in the session. You can instead write a custom UserDetailsService which returns an extended User object (or your own implementation of UserDetails) which contains your user details. I have written an article showing you how to do the same.
Now onto our filter. First the implementation :
public class MyAuthenticationProcessingFilter extends AuthenticationProcessingFilter {
@Override
protected void onSuccessfulAuthentication(HttpServletRequest request,
HttpServletResponse response, Authentication authResult)
throws IOException {
super.onSuccessfulAuthentication(request, response, authResult);
request.getSession().setAttribute("myValue", "My value is set");
}
}
Our filter simply sets a session attribute after a user successfully logs into the system.
This filter now needs to be plugged in. If you haven’t yet read the section on adding your own filters to spring security, I seriously suggest that you do, we’re going to use the information provided there to make spring security use our filter instead of the default one. To plug this filter in the following goes into your security-applicationContext.xml :
<bean id="authenticationProcessingFilter" class="com.codercorp.security.MyAuthenticationProcessingFilter"> <security:custom-filter position="AUTHENTICATION_PROCESSING_FILTER" /> <property name="defaultTargetUrl" value="/main.html" /> <property name="authenticationManager" ref="authenticationManager" /> </bean>
You also need to define an AuthenticationProcessingFilterEntryPoint since we’re going to break the default filter chain.
<bean id="authenticationProcessingFilterEntryPoint" class="org.springframework.security.ui.webapp.AuthenticationProcessingFilterEntryPoint"> <property name="loginFormUrl" value="/index.jsp" /> <property name="forceHttps" value="false" /> </bean>
And configure an AuthenticationManager as well :
<security:authentication-manager alias="authenticationManager" />
Your security-applicationContext.xml should look something like this :
<security:global-method-security /> <security:http auto-config="false" entry-point-ref="authenticationProcessingFilterEntryPoint"> <security:intercept-url pattern="/index.jsp" filters="none" /> <security:intercept-url pattern="/**" access="ROLE_USER" /> </security:http> <security:authentication-provider user-service-ref="customUserDetailsService" /> <bean id="customUserDetailsService" class="com.codercorp.security.CustomUserDetailsService" /> <bean id="authenticationProcessingFilter" class="com.codercorp.security.MyAuthenticationProcessingFilter"> <security:custom-filter position="AUTHENTICATION_PROCESSING_FILTER" /> <property name="defaultTargetUrl" value="/main.html" /> <property name="authenticationManager" ref="authenticationManager" /> </bean> <security:authentication-manager alias="authenticationManager" /> <bean id="authenticationProcessingFilterEntryPoint" class="org.springframework.security.ui.webapp.AuthenticationProcessingFilterEntryPoint"> <property name="loginFormUrl" value="/index.jsp" /> <property name="forceHttps" value="false" /> </bean>
Remember to switch off auto configuration of spring security by setting auto-config property of the http element to false. If you don’t you’ll get an exception :
Caused by: org.springframework.security.config.SecurityConfigurationException: Filters 'com.codercorp.security.MyAuthenticationProcessingFilter[ order=700; ]' and 'org.springframework.security.ui.webapp.AuthenticationProcessingFilter[ order=700; ]' have the same 'order' value. When using custom filters, please make sure the positions do not conflict with default filters. Alternatively you can disable the default filters by removing the corresponding child elements from <http> and avoiding the use of <http auto-config='true'>.
Your custom AuthenticationProcessingFilter is now ready for use and you can perform actions whenever a user logs in.
No related posts.

Thanks for that. Uou should add in the article to add entry-point-ref=”authenticationProcessingFilterEntryPoint” to the part, otherwise I couldn’t get it to work.
@mononoke:
Unless entry-point-ref is added, the example will not work.
Thanks for that info, I forgot to copy the new config once I had changed it.
Gaurav
Thank you for your post. Very helpful.
Hi all and thanks for helpful post.
i am little bit confused about session management.when i added request.getSession().setAttribute(”myValue”, “My value is set”); line my sessionlistener destroyed that session and creates a new one after redirecting to defaultTargetUrl.
i read your other post which is about user tracking already and tried to mix these but no success.
#AuthenticationProcessfilter
super.onSuccessfulAuthentication(request, response, authResult);
UserDetail userDetail = (UserDetail)authResult.getPrincipal();
request.getSession().setAttribute(”USER_DETAIL”, userDetail);
UserTracker.getInstance().addUser(userDetail);
#HttpSessionListener
public void sessionDestroyed(HttpSessionEvent sessionEvent) {
String sessionId = sessionEvent.getSession().getId();
UserTracker.getInstance().removeUser(sessionId);
}
#UserTracker
public synchronized void addUser(UserDetail userDetail){
loggedUsers.put(userDetail.getSessionId(),userDetail);
}
public synchronized void removeUser(String sessionId){
loggedUsers.remove(sessionId);
}
hell yes i found it.
that s about session fixation attack.for detailed solution http://static.springsource.org/spring-security/site/reference/html/ns-config.html#ns-entry-point-ref
thanks.
Glad you found it, was about to say that you should use the migrateSession option to have best of both worlds.
Thanks for your hints. They saved me a lot of time…
Any pointers on how to performs custom actions when the user logs out?
Implementing a standard HttpSessionListener might do the trick in most cases (although the Spring integration is quite clumsy) but session scoped beans are causing me problems. Everything works fine when user actually clicks the logout link but if the session times out I get a BeanCreationException from the session scoped beans.
Thats a very known problem. I’d suggest you simply catch the BeanCreationException and ignore it. The only time the exception can occur is when spring is not managing your logout and that can only happen when the session times out.
Hello Gaurav,
Thanks for this article. It certainly helps to resolve one issue I’m having.
What I now need is a way to have multiple elements in my web site. One which uses the auto-config=true (standard form based auth), and one which uses a custom element for RESTful access, with it’s own AuthEntryPoint.
I can easily create two filter-mappings in web.xml, but I have two problems :
a) Spring security (2.0.4) does not allow multiple http elements in your applicationContext files.
b) Most of the beans in my application are going to be shared with both the access points in my site (form based and REST based)
I’ve searched around, but haven’t found any examples on getting this resolved.
Would you have any suggestions on how would I go about doing that ?
Thanks,
Jalpesh.
Hello Gaurav,
Thanks for the post.
I have a requirement. After successful login the user is taken to the welcome page. From there he can click on a link to navigate to another page. In the second page, I need to display some details regarding the user logged in. So my requirement is, when the user clicks the link in Welcome page, it should be taken to the controller where there will be come calculations and store the value in a session variable. When the page is rendered, then the value is to be displayed .So my doubt is how we can access the session variable in Controller java classes. Or is there any other way to attain this functionality.
Please give me some pointers. I am new to spring. My application is using struts 2, spring, spring security and hibernate
Thanks,
SDB
You can access the session from the request..
Hi! thanks for this very usefull tutorial. Anyway reading it, when you say
“you don’t necessarily need to do all this work just to put your user’s details in the session. You can instead write a custom UserDetailsService which returns an extended User object (or your own implementation of UserDetails) which contains your user details.”
I followed the article and I implemented my UserDetailsService, but now How do I get user details from the session? I mean, in a JSP page how do I get for example the user email? because for the username I can do
But because the object “Principal” has a method called .getName()
How can I do a similar thing with other user details?
Many thanks in advance for the answer
Dario
the previus post didn’t show the following line
” ”
after “because for the username I can do ”
And before “But because the object ”
Sorry for the mess..
I have customized AuthenticationProcessingFilter for custom authentication. All working fine except, upon the unsuccess authentication, I like to display a custom message. So I am throwing BadCredentialExecption with the custom message. Upong the unsucessfull attempt, it never takes to the login page and never displays custom message. I see all the stacktrace on the page. URL shows j_spring_security_check.
Any idea pls? I appreciate it
@Override
protected void onUnsuccessfulAuthentication(HttpServletRequest request,
HttpServletResponse response, AuthenticationException failed) throws AuthenticationException, IOException
{
throw new BadCredentialsException(”Log In information not valid: Please enter a valid Username and associated Password.”);
}
Read this link on an idea of how to handle exceptions globally. This is possibly the easiest way to do it.
Great stuff!
everything almost works! but look at this:
here you wrote filters=”none”. if you replace this with access=”IS_AUTHENTICATED_ANONYMOUSLY” browser goes to unstoppable redirecting. do you know what is it?
Also spring security error handling dissapeared – server HTTP Status 401 error page now appears.
Hi!
I have the same problem. It works only for filters=”none”, but then the redirect to https (reqires-channel=”https”) doesn’t work… Any idea?