Thursday, 30 August 2007

How to implement remember me using acegi

I have extended the example application showing how to do form based login using acegi.

You need to apply the following changes to the securityContext.xml:

securityContext.xml (download)

Remember me beans:

<!-- remember me processing filter -->
<bean id="rememberMeProcessingFilter"
<property name="rememberMeServices" ref="rememberMeServices" />
<property name="authenticationManager" ref="authenticationManager" />

<bean id="rememberMeServices"
<property name="userDetailsService"> <ref local="memoryAuthenticationDao"/>
<property name="key" value="someTokenName"/>

<bean id="rememberMeAuthenticationProvider"
<property name="key" value="someTokenName"/>
Apply the following changes to existing beans:
Add the rememberMeServices to the logoutfilter for the logout filter to invalidate the remember me cookie.
<bean id="logoutFilter"
<constructor-arg index="0" value="/index.jsp"/>
<constructor-arg index="1">
<ref local="securityContextLogoutHandler"/>
<ref local="rememberMeServices"/>

Add the rememberMeProcessingFilter to the filterchain for the remember me checks to be performed when a user hits a acegi protected URI:
<bean id="filterChainProxy"
<property name="filterInvocationDefinitionSource">

Also remember to set the rememberMeServices at the authenticationProcessingFilter to overwrite the default NullRememberMeServices with your rememberMeServices. That will provide acegi with a service to handle remember me token validation (took me a bit of debugging to find this error)
<bean id="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"/>
<property name="rememberMeServices" ref="rememberMeServices"/>

Finally extend your login form with a checkbox to let your end user be remembered. The default parameter name is _acegi_security_remember_me:
<td>Remember me:</td>
<td><input type="checkbox" name="_acegi_security_remember_me"/></td>
Sample (download)
I also provided a simple webapp demonstrating the implementation, just:
  1. download
  2. unzip
  3. type $mvn jetty:run
  4. go to: http://localhost:8080/basicAcegiExample
  5. type user, password as credentials


Torsten said...

Pragmatic article, worked right away!

Jonny Symbols said...

Good article, but the code snippets omit the fact that you need to add the rememberMeAuthenticationProvider bean to the authentication manager's list of providers. If you do this, then it works :)

Jonny Cavell

Ben Alex said...

I just thought I'd note for the benefit of people finding this blog from 2008 onwards, Spring Security 2.0.0 (the new name for Acegi Security) now provides completely automatic remember-me functionality. You just need to leave the default configuration in your security application context as:

< http auto-config="true" >

If the above appears in your security application context file, you're set for remember-me. You can optionally fine-tune the settings via the <remember-me> sub-element.

These sort of configuration enhancements were a major theme of the 2.0.0 release. Previous application context files which took close to 200 lines can now be expressed in just 10 lines. Please use the new configuration syntax wherever possible; it is documented in our reference guide.

Hope you enjoy using Spring Security.

Best regards
Ben Alex
Principal Software Engineer, SpringSource
Project Lead, Spring Security (Acegi Security)

Anonymous said...

The correct link to what Ben Alex referred to is here

Dave Malone said...

Thanks for the writeup. Two things to mention regarding this configuration that I thought I would include. One, is that the placement of the remember me processing filter is not correct in your listing. See for more details.

Second, one thing I hadn't heard about before, but found out after my app was throwing exceptions, is that if you want to use the remember me processing filter with concurrent sessions enabled, and using the anonymous processing filter, you will need to set forceEagerSessionCreation on the HttpSessionContextIntegrationFilter

Read the following JIRA for more details:

Anonymous said...

Thanks, it works great :D