Welcome!

Java Authors: Maureen O'Gara, Bruce Armstrong, Liz McMillan, Walter H. Pinson, III, Yakov Werde

Related Topics: Java

Java: Article

Introduction to Acegi

Mastering the security framework

I recently evaluated the use of Acegi as the security framework for a Web development project. In the end, we decided to move forward with Acegi but in the beginning it took a couple days to come to that decision. The amazing thing is: once you get over the initial learning curve, it's smooth sailing. Hence, I wanted to share my experiences with it because first, I wanted to expose the Acegi security framework to JDJ readers and, second, I wanted to make it easier for JDJ readers to get over the initial learning curve. Once you're over that, you should be well on your way with Acegi.

Exposing Acegi Security Framework
Acegi is an open source security framework that allows you to keep your business logic free from security code. Acegi provides three main types of security:

  1. Web-based access control lists (ACL) based on URL schemes
  2. Java class and method security using AOP
  3. Yale's Central Authentication Service for single sign-on (SSO).
Acegi also provides the option of performing container security.

Acegi uses Spring as its configuration settings, so those familiar with Spring will be at ease with Acegi configuration. If you're not familiar with Spring, it's still easy to learn Acegi configuration by example. You don't have to use SpringMVC to secure your Web application. I have successfully used Acegi with Struts. You can use Acegi with WebWork and Velocity, Struts, SpringMVC, JSF, Web Services, and more.

Why use Acegi instead of JAAS? It can be difficult to stray from well-documented standards like JAAS. However, porting container-managed security realms is not easy. With Acegi, this security layer is an application framework that is easily ported. Acegi will allow you to easily reuse and port your "Remember Me," "I forgot my password," and log-in/log-out security functions to different servlet and EJB containers. If you have a standards-based security layer that you have re-created for numerous Java applications and it is not getting reused, you need to take a good look at Acegi. Besides, why are you spending time on framework coding when you should be focusing on the business logic? Leave the framework development to product developers and the open source community.

Getting Over That Initial Learning Curve
To get you over the initial learning curve, I'll take you through a simple setup using a demonstration application. I'll focus on the first security approach - URL-based security for Web applications because that's the most commonly used.

Installation
First things first - we need to install it! I'll use Tomcat 5 as my servlet container to illustrate.

Step 1: Set up a new Tomcat Web context with the "WEB-INF/", "WEB-INF/lib/", and "WEB-INF/classes" folders per usual (see Figure 1). I called my context "/acegi-demo" and access it using http://localhost:8080/acegi-demo/.

Step 2: Add another folder called "/secured," which we'll protect with Acegi.

Step 3: Now let's add the necessary Acegi library files to plug-in Acegi to our Tomcat context. (Please download the acegi-demo.zip file provided with this article from http://jdj.sys-con.com.)

Let's understand the JAR packages we are adding to the lib directory. The most important JAR is acegi-security-0.8.3.jar, the Acegi core library. Acegi leverages Spring for its configuration, so we also need spring-1.2.RC2.jar. The remaining JARs are utilities libraries for dealing with collections (commons-collections-3.1.jar), logging (commons-logging-1.0.4.jar, log4j-1.2.9.jar), and regular expressions (oro-2.0.8.jar). Special thanks to Apache Jakarta for these wonderful utility libraries.

Configuration
Now that we have our core infra-structure in place, let's focus on configuration.

Step 4: Configure the web.xml file (see Listing 1) to begin tying the Web application to the Acegi security framework.

  1. First, we need to set up two parameters: contextConfiguration, which will point to Acegi's configuration file, and log4jConfigLocation, which will point to Log4J's configuration file.
  2. Next, we have to set up the Acegi Filter Chain Proxy; this critical proxy allows Acegi to interact with the servlet filtering feature. We will talk about this more in step 5 (configuring applicationContext.xml).
  3. Finally, we want to add three listeners to loosely couple Spring with the Web context, Spring with Log4J and Acegi with the HTTP Session events in the Web context, such as create session and destroy session.
Step 5: Now we need to configure the applicationContext.xml (see Listing 2) to instruct the Acegi framework to perform our security requirements. It is important to note that you typically don't have to write or compile any code to fuse your application with the Acegi security framework. Acegi is almost entirely configuration driven, thanks to a great design by its creator, Ben Alex, and Spring. Okay, enough back patting, let's get to it...

Remember, the Acegi Filter Chain Proxy is critical. This is the backbone of the configuration. Using the servlet filter specification, Acegi is able to plug in its security functionality in a modular way.

I ordered the Spring bean references in the applicationContext.xml file based on the sequence each bean is referenced, starting with the filterChainProxy bean. If you are new to Spring, just know that the order in which a bean is referenced is not important. I ordered it this way to make it as easy as possible to follow along.

<bean id="filterChainProxy" class="net.sf.acegisecurity.util.FilterChainProxy">
    <property name="filterInvocationDefinitionSource">
     <value>
     CONVERT_URL_TO_LOWERCASE_BEFORE_COMPARISON
     PATTERN_TYPE_APACHE_ANT
   /**=httpSessionContextIntegrationFilter, authenticationProcessingFilter,
   anonymousProcessingFilter, securityEnforcementFilter
     </value>
    </property>
   </bean>

In the filterChainProxy bean (see code snippet above), we tell Acegi that we want to use lowercase for all URL comparisons and use the Apache ANT style for pattern matching on the URLs. In our example, we run the filterChainProxy on every single URL by specifying /**=Filter1,Filter2, etc. Next, we set up the filter chain itself, where order is very important. We have four filter chains in this simple example, but when you start using Acegi, you'll most likely have more. Viewing applicationContext.xml, please take a few moments to follow all the bean references in great detail as you traverse the filter chain. I will walk through each item in the filter chain at a high level.

The first item in the chain must be the httpSessionContextIntegrationFilter filter. This filter works hand-and-hand with the HTTP Session object and the Web context to see if the user is authenticated and, if so, then what roles the user has. We have little to configure for this filter.

The second item in the chain is the authenticationProcessingFilter filter, which searches for any URL that matches /j_acegi_security_check because this is the URL that our login form will post a username and password to when attempting authentication. This filter also contains the configuration information detailing where to send someone if the login succeeds or fails. If it succeeds, you can configure this filter to direct the user to the page the user originally tried to access or direct the user to a particular start page where you want all authenticated users to land after authentication. I have the latter option configured in my example by setting alwaysUseDefaultTargetUrl to true and you just set it to false to get the former option.

One of the beans configured in the authenticationProcessingFilter is the authenticationManager bean. This bean manages the various providers you configure. A provider is essentially a repository of usernames with corresponding passwords and roles. The authenticationManager will stop iterating through the list of providers once a user is successfully authenticated. In practice, you may have two or three providers; for example, one provider could access an Active Directory for employee credentials, while your second provider might access a database for customer credentials. You will most often need an anonymousAuthenticationProvider because you need it to allow access to pages that do not requiring authentication to access, such as the login page or the home page. The demonstration application for this article uses a memory provider and an anonymous provider. Once you get this simple application working, you probably want to add a JDBC or LDAP provider.

The third item in the chain is the anonymousProcessingFilter filter. This will match the value created by the anonymousAuthenticationProvider.

The fourth and final item in the filter chain is the securityEnforcementFilter filter. This filter has two beans: the filterSecurityInterceptor and the authenticationProcessingFilterEntryPoint. The latter bean is used to direct the user to the login form each time the user tries to access a secured page but is not logged in. We can also force the user to use HTTPS. The former bean, filterSecurityInterceptor, does quite a bit of heavy lifting by tying all our filters together.

More Stories By David Hardwick

David Hardwick has 9 years of IT industry experience in B2B, non-profit, and public sector industries. He is manager of technology at Sapient Corporation where he is involved in application development and technology consulting.

Comments (13) View Comments

Share your thoughts on this story.

Add your comment
You must be signed in to add a comment. Sign-in | Register

In accordance with our Comment Policy, we encourage comments that are on topic, relevant and to-the-point. We will remove comments that include profanity, personal attacks, racial slurs, threats of violence, or other inappropriate material that violates our Terms and Conditions, and will block users who make repeated violations. We ask all readers to expect diversity of opinion and to treat one another with dignity and respect.


Most Recent Comments
Aymens 08/25/08 09:46:11 AM EDT

I'd like to think you for this article, good and simple!

While reading, I was wondering how could we manage 'Roles'? Can we add meaning to roles ? And build them based on rights (MANAGER_ROLE=READ, WRITE, DELETE ...

Vitaly 09/01/06 01:58:15 PM EDT

I'm looking for a way to integrate Struts, Acegi and Spring in a web application. It turns out that you have to either load context files with context listener registered in web.xml (Acegi+Spring integration) or with a struts plugin (Struts+Spring integration). But I don't want to separate my context into 2 parts: one for security and the other for the whole application. I might need security beans inside of the application. Currently at least one bean - dataSource is shared by acegi and struts (Hibernate).

Mahmood Khan 08/25/06 01:27:31 AM EDT

Will it work for Desktop based applications using J2EE architecture. Client, Application Servers (EJB's) and Database.

JDJ News Desk 08/02/06 08:41:35 AM EDT

I recently evaluated the use of Acegi as the security framework for a Web development project. In the end, we decided to move forward with Acegi but in the beginning it took a couple days to come to that decision. The amazing thing is: once you get over the initial learning curve, it's smooth sailing. Hence, I wanted to share my experiences with it because first, I wanted to expose the Acegi security framework to JDJ readers and, second, I wanted to make it easier for JDJ readers to get over the initial learning curve. Once you're over that, you should be well on your way with Acegi.

srihari konakanchi 08/02/06 07:34:55 AM EDT

excellent article for quick start with acegi.
It would be nice if there more details about pros & cons with JAAS and acegi without spring
--srihari

Balagopal 04/25/06 06:26:12 AM EDT

David

Can u please suggest some steps to migrate from InMemoryDaoImpl to JdbcDaoImpl.

Bala

karthik N 03/07/06 06:03:46 AM EST

nice article, how about instance based security demo?

Vikas Hazrati 03/03/06 07:38:06 AM EST

I made the following change

CONVERT_URL_TO_LOWERCASE_BEFORE_COMPARISON
PATTERN_TYPE_APACHE_ANT
/acegilogin.jsp*=ROLE_ANONYMOUS,ROLE_USER,ROLE_ADMIN
/secured/*=ROLE_ADMIN
/**=ROLE_USER

and it seems to be working now.

Any comments?

Further you might also want to look at the welcome file, change it to something as there is no index.jsp present if I hit

http://localhost:8080/acegi-demo

Vikas Hazrati 03/03/06 07:22:13 AM EST

I deployed the application and tried playing around with it on tomcat.

The question is regarding
.....
CONVERT_URL_TO_LOWERCASE_BEFORE_COMPARISON
PATTERN_TYPE_APACHE_ANT
/acegilogin.jsp*=ROLE_ANONYMOUS,ROLE_USER,ROLE_ADMIN
/secured*=ROLE_ADMIN
/**=ROLE_USER

I assume that this means that anything under the secured folder would be accessible by anyone having a ROLE_ADMIN. Correct?

I created a user with the ROLE_USER as

.....

sapient=password,ROLE_ADMIN,ROLE_USER
vikas=password,ROLE_USER

....

Now even if i login with Vikas I am able to access the secured area.

Am I missing something?

Vikas Hazrati 03/03/06 07:22:03 AM EST

I deployed the application and tried playing around with it on tomcat.

The question is regarding
.....
CONVERT_URL_TO_LOWERCASE_BEFORE_COMPARISON
PATTERN_TYPE_APACHE_ANT
/acegilogin.jsp*=ROLE_ANONYMOUS,ROLE_USER,ROLE_ADMIN
/secured*=ROLE_ADMIN
/**=ROLE_USER

I assume that this means that anything under the secured folder would be accessible by anyone having a ROLE_ADMIN. Correct?

I created a user with the ROLE_USER as

.....

sapient=password,ROLE_ADMIN,ROLE_USER
vikas=password,ROLE_USER

....

Now even if i login with Vikas I am able to access the secured area.

Am I missing something?

rakesh patel 02/19/06 05:05:55 AM EST

hi,

i could not get your demo to deploy to my app server Sun Application Server 8.1.

I changed your original web.xml file to be Servlet 2.4 compatible by changing the first few lines. The error i recieve on deployment is:

[#|2006-02-19T08:35:17.881+0000|SEVERE|sun-appserver-pe8.1_01|javax.enterprise.system.tools.deployment|_ThreadID=14;|Exception occured in J2EEC Phase
com.sun.enterprise.deployment.backend.IASDeploymentException: Deployment Error -- java.net.URISyntaxException: Illegal character in path at index 19: file:///acegi-demo_\acegi-demo

Any ideas???

Thanks

Rakesh

Roko Roic 02/17/06 01:15:41 PM EST

This is exactly what the world needed, a simple and "for the dumb" ACEGI walkthru. Thank you.

SYS-CON Italy News Desk 02/02/06 03:19:35 PM EST

I recently evaluated the use of Acegi as the security framework for a Web development project. In the end, we decided to move forward with Acegi but in the beginning it took a couple days to come to that decision. The amazing thing is: once you get over the initial learning curve, it's smooth sailing. Hence, I wanted to share my experiences with it because first, I wanted to expose the Acegi security framework to JDJ readers and, second, I wanted to make it easier for JDJ readers to get over the initial learning curve. Once you're over that, you should be well on your way with Acegi.