miyukiutada
Photo credit: miyukiutada
del.icio.us Digg DZone Reddit StumbleUpon
Software Development

Overview of Acegi

Get an overview of Spring's Acegi security in five minutes.

Acegi has been around for a while, but I just recently tried it out and am impressed with it so far. Upon first glance Acegi is slightly intimidating because there are lots of classes involved, and it may be hard to keep them straight. Fortunately Acegi is actually straightforward, despite appearances, to anybody who already understands servlet filters and the basics of Spring bean configuration.

The overarching idea is that Acegi provides a suite of security services (mostly if not entirely around authentication and authorization) based on servlet filters. So for example there are filters for accepting user logins, enforcing access controls, catching security-related exceptions, handling logouts, handling "remember me" functionality for logins, switching from HTTP to HTTPS, etc. So using Acegi mostly involves deciding which of the filters you want (e.g., maybe you want "remember me", maybe you don't) and then configuring those into the app.

Acegi involves dependency injection into servlet filters (say what?)

Acegi does get a little interesting though because the various filters rely upon Spring's dependency injection, but the standard way of configuring servlet filters into web.xml does not support Spring dependency injection. (The web.xml schema doesn't have anything for dependency injection, nor should it.) Acegi uses a pretty neat trick to give us injectable servlet filters. What it does is it provides a Filter implementation called FilterToBeanProxy that you configure in like this:

<filter>
    <filter-name>security</filter-name>
    <filter-class>org.acegisecurity.util.FilterToBeanProxy</filter-class>
    <init-param>
        <param-name>targetClass</param-name>
        <param-value>org.acegisecurity.util.FilterChainProxy</param-value>
    </init-param>
</filter>
 
<filter-mapping>
    <filter-name>security</filter-name>
    <url-pattern>/*</url-pattern>
</filter-mapping>

Pretty standard stuff. The idea behind FilterToBeanProxy is that it knows about your [appname]-security.xml bean configuration file, and so it can load in any beans that you define there. In web.xml we tell FilterToBeanProxy to load in a FilterChainProxy defined in [appname]-security.xml. FilterChainProxy, as its name suggests, is a FilterChain implementation. In turn, inside [appname]-security.xml we configure the various Filter beans mentioned above into the FilterChainProxy. Here's how it looks:

<bean id="filterChainProxy" class="org.acegisecurity.util.FilterChainProxy">
    <property name="filterInvocationDefinitionSource">
        <!-- IMPORTANT: DON'T LINEBREAK THE FILTER LIST, OR ELSE BEAN LOOKUP BREAKS! -->
        <!-- I'M JUST DOING IT HERE FOR DISPLAY PURPOSES -->
        <value>
            CONVERT_URL_TO_LOWERCASE_BEFORE_COMPARISON
            PATTERN_TYPE_APACHE_ANT
            /**=httpSessionContextIntegrationFilter,logoutFilter,
authenticationProcessingFilter,exceptionTranslationFilter,filterSecurityInterceptor
        </value>
    </property>
</bean>

The list of filter names is just a list of beans that you also configure in the same [appname]-security.xml config file. Here's an example:

<bean id="httpSessionContextIntegrationFilter"
    class="org.acegisecurity.context.HttpSessionContextIntegrationFilter"/>

Voila, injectable servlet filters! Very cool.

Be careful of the following gotchas

There are some points/gotchas worth mentioning:

  1. The servlet filters must be added in a specific order. If you get the order wrong, it won't work, since the servlet filters make assumptions about what kind of processing has already taken place. Check the Acegi docs for details.
  2. If you're using other servlet filters (such as Sitemesh), the Acegi filters need to come before the others.
  3. When configuring FilterChainProxy, you will need to map URL patterns to the list of filters that you want to service requests matching those patterns. For example, you might map /** (Ant syntax) to a list of four filters. The list is comma-delimited. It is important that you not include line breaks after the commas. I'm guessing you can't include whitespace at all, but for sure you can't include line breaks. Otherwise you will get Bean not found: '' exceptions, without any explanation as to what the actual problem is. I'm surprised they don't allow the line breaks since I figure many people will naturally want to break up a long list of filters with long names, but my surprise notwithstanding, the line breaks aren'

Here's a JavaWorld article on getting started with Acegi. Also, Spring in Action has some good instructions.

Social bookmarks: del.icio.us Digg DZone Reddit StumbleUpon
Show comments (0)

Post a comment

Your name:
Your e-mail address (won't be displayed):
Your web site (optional):
example: www.xyz.com
Your comment:
Please help us prevent comment spam:
Spring in Practice
My brother and I are writing Spring in Practice for Manning!

What's New?

2008-10-20 - I've added a new mailing list feature to the site. Sign up to receive e-mail updates about new articles.
2008-09-30 - We've released chapter 4 (User registration) and chapter 5 (Authentication) of Spring in Practice.
2008-09-11 - By popular demand, I've added an RSS feed to the site.
Home | Consulting | Tech Articles | Mailing List | About | Contact | Spring Blog
Copyright © 2008 Wheeler Software, LLC.