
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 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.
There are some points/gotchas worth mentioning:
/** (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.