WebFacetsHOW-TOsAuthentication
YourKit Java Profiler |
AcegiAcegi 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 :
In Acegi, custom authentication is done by providing an implementation of the 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 modelsAcegi'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...
Common datasourceThe 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 It can handle "flat" roles (no hierarchy) by default. Handling hierarchical roles is explained below. Hierarchical rolesThe 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 Authorization with hierarchical rolesIn order to have hierarchical roles working also for Access Control, we use the To enable this, you simply have to implement @Override public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException, DataAccessException { UserDetails userDetails = ... ; if (userDetails == null) return null; else return new HierarchicalUserDetails(this, userDetails); }
Spring configurationFirst 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 <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 applicationA 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. |