Before I go on to describe what goes into it, thanks to the following. These links are a bit dated, but they did help me along.
Custom AuthenticationProcessingFilter for spring security to perform actions on login
An example of the security config for a custom auth filter (see last post)
Spring's documentation on adding own filters
Now, here we go. What is described below works for Spring Security 3.0.0.RELEASE.
1. We need to extend UsernamePasswordAuthenticationFilter
It used to be AuthenticationProcessingFilter, which is depricated.
In this example, we just write to the console. You would do something more important.
public class CustomUsernamePasswordAuthenticationFilter extends
UsernamePasswordAuthenticationFilter {
@Override
protected void successfulAuthentication(HttpServletRequest request,
HttpServletResponse response, Authentication authResult)
throws IOException, ServletException {
super.successfulAuthentication(request, response, authResult);
System.out.println("==successful login==");
}
@Override
protected void unsuccessfulAuthentication(HttpServletRequest request,
HttpServletResponse response, AuthenticationException failed)
throws IOException, ServletException {
super.unsuccessfulAuthentication(request, response, failed);
System.out.println("==failed login==");
}
}
2. In spring security context, we will be overriding the form login filter FORM_LOGIN_FILTER.
This used to be AUTHENTICATION_PROCESSING_FILTER, which is not used now.
<http ...
<custom-filter position="FORM_LOGIN_FILTER" ref="customUsernamePasswordAuthenticationFilter">
Note: Since we are replacing the default FORM_LOGIN_FILTER, we should not use <form-login login-page... , as that will try to create the default filter and you would get an exception (that there are two filters defined at the same position).
3. Since we are using the custom FORM_LOGIN_FILTER, we need to set the following property on <http ..
<http auto-config="false"
4. Another thing to set at <http is entry-point-ref
Again, since we are altering the default behavior, we need to tell what is the entry point for the form login.
<http entry-point-ref="loginUrlAuthenticationEntryPoint"
And, correspondingly, define the loginUrlAuthenticationEntryPoint bean. Note that LoginUrlAuthenticationEntryPoint used to be AuthenticationProcessingFilterEntry which is depricated.
<beans:bean id="loginUrlAuthenticationEntryPoint"
class="org.springframework.security.web.authentication.LoginUrlAuthenticationEntryPoint">
<beans:property name="loginFormUrl" value="/login.html">
</beans:bean>
5. Remember the filter 'customUsernamePasswordAuthenticationFilter ' we used in in step 2 and extended in step 1, we have to define it.
<beans:bean id="customUsernamePasswordAuthenticationFilter"
class="com.yourapp.web.security.CustomUsernamePasswordAuthenticationFilter" >
<beans:property name="authenticationManager" ref="authenticationManager">
<beans:property name="authenticationFailureHandler" ref="failureHandler">
<beans:property name="authenticationSuccessHandler" ref="successHandler">
</beans:bean>
<beans:bean id="successHandler" class="org.springframework.security.web.authentication.SavedRequestAwareAuthenticationSuccessHandler">
<beans:property name="defaultTargetUrl" value="/login.html">
</beans:bean>
<beans:bean id="failureHandler" class="org.springframework.security.web.authentication.SimpleUrlAuthenticationFailureHandler">
<beans:property name="defaultFailureUrl" value="/login.html?login_error=true">
</beans:bean>
6. In the definition of 'customUsernamePasswordAuthenticationFilter' we are identifying the 'authenticationManager', so when you define your authentication manager provide an 'alias' for it:
<authentication-manager alias="authenticationManager">
...
</authentication-manager>
There you have it. Share and enjoy.
Thank you very much -- this was helpful!
ReplyDeleteThanks ... came in handy :)
ReplyDeleteThank you very much.
ReplyDeleteThe move from AuthenticationProcessingFilter too UsernamePassword things was just to painful for me until I got your blog
great job, thank
ReplyDeletehi i am updating 2.X to 3.0.3 spring security
ReplyDeleteas you told i need to remove the following line from
but where should i mention 'login-processing-url="/j_security_check" '
or there is not a problem removing that line .. please help me
itsdipak@gmail.com
Hi,
ReplyDeleteI have fallowed your steps, but at the end my login page goes into redirect loop. Can you help me.
This was of great help and good learning.
ReplyDeletegreat resource!
ReplyDeleteThanks a lot for bean wiring examples!
ReplyDeleteBy the way there is another way of retrieving user information to session or using authentication information - extending UserDetailsService class:
http://www.codercorp.com/blog/spring/security-spring/writing-custom-userdetailsservice-for-spring-security.html
David, this is true, but with real session management your things there are stateful. Everything in the security context is immutable unless you create a new authentication object. I think you only really want to do this when you're changing the password or some other specific security setting. It's not transactional the way a session can be.
ReplyDeleteLove this tutorial, but if the overriding of the default username password authentication filter was for the purpose of adding something into the session, I don't know how effective it will be. The login filter is fired before the session_management filter in the filter chain and if you have Spring Security configured to avoid session fixture attacks your session objects added right after successful authentication might get dropped when that filter runs.
ReplyDeletethanks, saved my day.
ReplyDeleteThis comment has been removed by the author.
ReplyDeleteFor all of you guys wondering about j_security_check and login page looping. Default url for sping security is j_spring_security_check.
ReplyDeleteJust replace your login form with "form method="POST" action="j_spring_security_check".
Or add property name="filterProcessesUrl" value="/j__security_check" to your filter configuration.
I think it's a common question. Would be nice to include it in the post.
Thank you so much. This post is very detailed one. If we use some technique, we should know all the work around also. You have explained it clearly. Thanks again. Please post more.
ReplyDeleteThank you so much! You're a lifesaver.
ReplyDeleteWow.. to use just one custom bean, the whole security config has to be manually wired. Would have been nice to use auto-config while manually injecting only this bean.
ReplyDeletevery nice!
ReplyDeleteCool and that i have a super offer: What Home Renovation Shows Are On Netflix house renovation advice
ReplyDelete