How to implement formbased authentication with acegi - no container dependencies
I couple of days ago I implemented a sample application illustration the minimal configuration needed for doing basic authentication using acegi. I have decided to take the next step and show a sample of a form based authentication solution - still without any container dependencies. Having no dependencies to a specific container seems to gain a bit of momentum in the Java community these days and Per wrote a interesting blog about keeping your deployment thin and lightweight.
Based on my last basic authentication example you only need to change the following:
See securityContext.xml (download)
ProcessingFilter
Switch the basicProcessingFilter with this one:
<!-- Processes formbased authentication.
The html form should contain to input fields: j_username and j_password.
The post of the form should point at the value of the "filterProcessesUrl"
in this case /j_acegi_security_check -->
<bean id="authenticationProcessingFilter"
class="org.acegisecurity.ui.webapp.AuthenticationProcessingFilter">
<property name="authenticationManager" ref="authenticationManager"/>
<property name="authenticationFailureUrl" value="/index.jsp?login_error=1"/>
<property name="defaultTargetUrl" value="/secure/securecontent.jsp"/>
<property name="filterProcessesUrl" value="/j_acegi_security_check"/>
</bean>
Also remember to change the use in your filterChainProxy.
...AuthenticationEntryPoint
/**=httpSessionContextIntegrationFilter,authenticationProcessingFilter,exceptionTranslationFilter,filterInvocationInterceptor
...
Switch authenticationEntryPoint with this:
<!-- changed to work with formbased login -->Further I changed the UserDetailsService as my own implementation could be swapped with an org.acegisecurity.userdetails.memory.InMemoryDaoImpl and still be a lightweight in memory userdetails implementation for the sake of the example:
<bean id="authenticationEntryPoint"
class="org.acegisecurity.ui.webapp.AuthenticationProcessingFilterEntryPoint">
<property name="loginFormUrl" value="/index.jsp"/>
</bean>
<!-- implemented memory dao -->Logout
<bean id="memoryAuthenticationDao"
class="org.acegisecurity.userdetails.memory.InMemoryDaoImpl">
<property name="userMap">
<value>user=password,USER</value>
</property>
</bean>
Contrary to basic authentication you are able to let the user logout without closing the browser.
Add the following logoutFilter to the filterChainProxy
...and create a logout handler like the SecurityContextLogoutFilter:
/**=httpSessionContextIntegrationFilter,authenticationProcessingFilter,logoutFilter,exceptionTranslationFilter,filterInvocationInterceptor
...
<bean id="logoutFilter" class="org.acegisecurity.ui.logout.LogoutFilter">This snippet will handle a logout when the user requests the /j_acegi_logout that is the default url. Can be changed as a parameter to the logout filter.
<constructor-arg index="0" value="/index.jsp"/>
<constructor-arg index="1">
<list>
<ref local="securityContextLogoutHandler"/>
</list>
</constructor-arg>
</bean>
<bean id="securityContextLogoutHandler"
class="org.acegisecurity.ui.logout.SecurityContextLogoutHandler" />
Actually I found this api documentation for the BasicProcessingFilterEntryPoint indicating that it is possible to logout using basic authentication without killing the browser:
/**I tried the suggested commence solution in my basic autentication example, but did not have success. If you are able to implement the commence solution let me know.
* Used by the <code>SecurityEnforcementFilter</code> to commence authentication via the {@link
* BasicProcessingFilter}.<P>Once a user agent is authenticated using BASIC authentication, logout requires that
* the browser be closed or an unauthorized (401) header be sent. The simplest way of achieving the latter is to call
* the {@link #commence(ServletRequest, ServletResponse, AuthenticationException)} method below. This will indicate to
* the browser its credentials are no longer authorized, causing it to prompt the user to login again.</p>
*
* @author Ben Alex
* @version $Id: BasicProcessingFilterEntryPoint.java 1877 2007-05-25 05:33:06Z benalex $
*/
Sample (download)
I also provided a simple webapp demonstrating the implementation, just:
- download
- unzip
- type $mvn jetty:run
- go to: http://localhost:8080/formbasedAcegiExample
- type user, password as credentials
Using formbased login you can easy implement "remember me" functionality.
Further documentation
- The official Acegi documentation
- Another formbased Acegi example using JSTL.
2 comments:
Hi,
Your article is good, but i want to overwrite LogoutFilter class. bcos i want to do some operation when i logout. I wrote a class also. But the problem is when i start my server it is automatically calls my UserDefinedLogoutFilter, but i want to call this class only when i logout, do you have any idea why it is happening like this. I wrote another class for AuthenticationProcess, tat one works fine.it call only when i click login button. only logout creating issue.
The logoutfilter already specified in the context.xml takes a list of logouthandlers.
Maybe you implement your own and add it to the list?
Currently only the securityContextLogoutHandler is registered, but you can add you own to the list.
Post a Comment