Thursday, September 15, 2005

Acegi Security Introduction

Lately I've been busy learning and trying out the Acegi Security System, which is a security framework for the Spring Framework. It's not the easiest framework to grasp, but if you have the time and will, it will pay off. During the process of learning it, I created a diagram to help me understand, and now I decided to create a small introduction around it.
Remember, this is just an example of a possible Acegi configuration. Acegi Security is very flexible and has a lot more features (like single-sign-on and remember-me services).


Introduction

Acegi is based on servlet filters. This has one big advantage: it decouples your application from Acegi. And this makes it easier to add Acegi to an already working application, for example.
For simplicity sake, there's no need to declare all filters on the web.xml. You can use FilterChainProxy which encapsulates a group of filters and executes them in order. As you can see in the picture, we can have 3 filters lined up. Ignoring the HttpSessionIntegrationFilter for now, the other two, AuthenticationProcessingFilter and SecurityEnforcementFilter, implement Authentication and Authorization, respectively.


Authentication

Authentication is the process of confirming that a user is who he claims to be. Typically, this is done by supplying an username and a password (in Acegi concepts those are called Principal and Credentials, respectively). In a web environment, normally, the username and password are provided as a result of an HTML form submit. This submission is captured by the AuthenticationProcessingFilter (it analyzes the URLs passing by, looking for the configured string, that is passed by the form's "action" property) AuthenticationProcessingFilter then calls AuthenticationManager, which starts the process of authenticating. First step is to find the user in some repository, based on the given username. Next, the credentials are compared, and if they are equal, authentication is successful.

The base class in this process is the Authentication class. It's a simple bean composed of a Principal, Credentials and a few Authorities (this normally means user "roles"). AuthenticationProcessingFilter creates a new Authentication Object with the specified username and password, and if authentication succeeds, at the end of the process the Authentication Object will be filled with some Authorities.
But first, we need to find the claimed user in the system. There can be a variety of user repositories in the system (database, ldap, etc). Each of these repositories can be accessed through an AuthenticationProvider. The role of the AuthenticationManager is to maintain a collection of these providers.

Acegi has a few different types of AuthenticationProviders, but probably the most used is the DaoAuthenticationProvider. This AuthenticationProvider uses a DAO (Data Access Object) to retrieve the user from a repository (typically a database). You can use the provided JdbcDaoImpl to connect to a database through JDBC and retrieve the user information, without writing any code. However, is quite simple to implement your own Dao (I did it because I was using Hibernate): just one method that retrieves a User based on a username.

Authorization

Authorization is the process of protecting resources by only allowing those resources to be used by users that have been granted authority to use them. SecurityEnforcementFilter is the filter responsible for the authorization process. It uses a FilterSecurityInterceptor to identify the resources that need to be secured. It holds a collection of patterns (regular expressions) and authorities (an Authority is normally just a string representing an user role). When an URL is identified by one of the patterns, the related authorities must be present in the Authentication object (the one that was created by the authentication process). If there is no Authentication object (the user has not logged in yet) or if the given Authentication does not have the authorities the resource requires, then the application is redirected to a configured AuthenticationProcessingFilterEntryPoint. This normally just represents an URL to a login form.


Now for the first filter, HttpSessionIntegrationFilter...this is responsible for integrating the Authentication object with the HTTP Session. The authentication and authorization processes talked before don't really interact with the HTTP Session. They aren't even aware there is such a thing. They use a SecurityContextHolder to retrieve a SecurityContext, which contains the Authentication object. When a request is made, HttpSessionIntegrationFilter loads the SecurityContext from the Session and stores it in the SecurityContextHolder, where all subsequent filters can access it. At the end of the request, the SecurityContext (that may have been altered during the request) is stored again in the Session. This kind of design is very flexible... all the authentication and authorization processes are independent of HTTP session handling. Thus, we could provide a SecurityContext in any other way. HttpSessionIntegrationFilter it's just a thin layer on top of the rest of the Acegi Security System.

1 comentários:

ThinkEddy said...

Great write up! Acegi has been extremely helpful in helping us implement a system-wide security layer over a large application with disparate modules and servlets.