Recent Changes - Search:

WebFacets

HOW-TOs

Authentication



SourceForge Logo









YourKit Java Profiler

Acegi

Acegi is a well known security system for the Spring framework. It enables pluggable authentication and access control in Spring applications (J2EE or desktop).

WebFacets itself does not deal with authentication. But of course, authentication and profiling are related stuff : as a matter of fact, you have to know who is requesting for something if you want it to be profiled ! From this point of view, Acegi and WebFacets are complementary technlologies that can be used together in order to build profile-based webapps ! The idea is to :

  • rely on Acegi for authentication of incoming users and role-based protection of some resources (Access Control) ;
  • use WebFacets for presenting profiled pages to the end-users, based on their identity.

In Acegi, custom authentication is done by providing an implementation of the UserDetailsService. This simple interface (javadoc here) is used by the framework in order to query infos about users and perform authentication and authorization. Basically, the UserDetailsService knows about the user's password and roles (a.k.a. Granted Authorities).

In WebFacets, we use the Profile Repository (javadoc here) in order to represent users and roles as a graph of profiles that the framework navigates in order to locate facets.

The issue is to have a common datasource for users and roles, used by Acegi AND WebFacets. Both frameworks rely on this info to perform their work, and both support pluggable "repositories" via Spring IoC...

Differences in the users/roles models

Acegi's users/roles model is "flat" : users can have multiple roles, but roles aren't organized hierarchically (no parent/child relationship between roles). This is probably due to the fact that Acegi is compliant with the JEE security model, which is flat too.

This is not a technical problem, since JFacets supports flat roles (who can do more can do less). It's more a philosophical debate : hierarchical roles or not ? If you're used to facet-based developpement, you may already have made your choice ! Hierarchical profiles are pretty natural to represent real-life scenarios, and are very handy for factorizing code.

Anyway, this difference can be handled at a ver small cost, as shown in a few moments...

NOTE
I've just figured out that it was already work in progress : there's a Feature request in Acegi ! TBC !

Common datasource

The main issue for having Acegi and WebFacets work together is to have a common datasource for users and roles. Both frameworks rely on this info to perform their work, and both support pluggable "repositories". The WebFacets Profile Repository should use the same informations than Acegi's UserDetailsService.

To do so, we use the AcegiProfileRepository, which implements an Acegi-compliant Profile Repository for WebFacets. It relies on the userDetailsService in order to provide users/roles informations.

It can handle "flat" roles (no hierarchy) by default. Handling hierarchical roles is explained below.

Hierarchical roles

The IHierarchicalUserDetailsService interface, which extends UserDetailsService, allows handling of hierarchical roles.

package net.sourceforge.jfacets.acegi;

import org.acegisecurity.GrantedAuthority;
import org.acegisecurity.userdetails.UserDetailsService;

/**
 * An extension of Acegi's UserDetailsService for managing
 * roles inheritance.
 */

public interface IHierarchicalUserDetailsService extends UserDetailsService {

        /**
         * Return a GrantedAuthority for passed role name (null if not found)
         */

        GrantedAuthority getGrantedAuthority(String roleName);

        /**
         * Return an array of parent roles for passed G.A. (null or 0-length array if no parents)
         */

        GrantedAuthority[] getParentRoles(GrantedAuthority grantedAuthority);

}

You simply have to implement this interface instead of the base UserDetailsService in order to get hierarchical roles up and running, at least in the WebFacets part.

Authorization with hierarchical roles

In order to have hierarchical roles working also for Access Control, we use the HierarchicalUserDetails class, which wraps the regular UserDetails and allows to get the list of all roles endorsed by the user (not only the first level ones).

To enable this, you simply have to implement loadUserByUsername in your IHierarchicalUserDetailsService, so that it returns HierarchicalUserDetails objects instead of the original UserDetails ones, like this :

@Override
        public UserDetails loadUserByUsername(String username)
                        throws UsernameNotFoundException, DataAccessException {
                UserDetails userDetails = ... ;
                if (userDetails == null)
                        return null;
                else
                        return new HierarchicalUserDetails(this, userDetails);
        }

NOTE
You can find an example of implementation of the IHierarchicalUserDetailsService in net.sourceforge.jfacets.acegi.InMemoryHierarchicalUDS.

Spring configuration

First off, the two contexts have to be loaded, so you have to configure the Spring ContextLoader filter/servlet something like :

<context-param>
                <param-name>contextConfigLocation</param-name>
                <param-value>
                        /WEB-INF/hierarchical/applicationContext-acegi-security.xml,
                        /WEB-INF/hierarchical/applicationContext-webFacets.xml
                </param-value>
        </context-param>

Then, you have to configure the applicationContext-acegi-security.xml so that you use the appropriate User Details Service :

<bean id="userDetailsService" class="net.sourceforge.jfacets.acegi.InMemoryHierarchicalUDS">
                <property name="userProperties">
                        <bean class="org.springframework.beans.factory.config.PropertiesFactoryBean">
                                <property name="location" value="/WEB-INF/users.properties"/>
                        </bean>
                </property>
                <property name="roleProperties">
                        <bean class="org.springframework.beans.factory.config.PropertiesFactoryBean">
                                <property name="location" value="/WEB-INF/hierarchical/roles.properties"/>
                        </bean>
                </property>
        </bean>

And finally, configure the WebFacets context to use the Acegi ProfileRepository with specified UserDetailsService :

<!--  import the userDetailsService from the WebFacets context -->
        <import resource="applicationContext-acegi-security.xml"/>

        <!--                               -->
        <!--    Acegi-enabled ProfileRepository    -->
        <!--                               -->
        <bean id="profileRepository" singleton="true" 
                        class="net.sourceforge.jfacets.acegi.AcegiProfileRepository">

                <property name="userDetailsService"><ref bean="userDetailsService"/></property>
        </bean>

Example application

A simple example project using both WebFacets and Acegi is available in the CVS, in the JFacets2-acegi module.

It's an enhanced version of the "Tutorial Sample", included in the Acegi distro, that adds a basic profiling example. It demonstrates both flat and hierarchical roles.

Edit - History - Print - Recent Changes - Search
Page last modified on September 18, 2006, at 09:44 PM