Configuring the DataSource UserManager

Written by Hani Suleiman

Concepts

 

Users:

A user is an entity that has at least a username and password, and optionally any number of other properties (for example first name, last name, address, and so on). In this example we'll constrain ourselves to the base case, which is a user with a username and a password.

Groups:

A group is a collection of users. A group has a name, and a list of users that belong to this group. The mapping of users to groups is many to many. A user can belong to more than one group.

Roles:

A role is distinct from a group. The role is tied to the application, and the groups are tied to the deployment. For authentication purposes, it's very important to realise that roles are NOT groups. The two terms are not used interchangeably. This distinction often causes much confusion. A role can contain any number of groups (a group can also belong to multiple roles). A role can also contain any number of users.

Scenario:

Lets us assume that we have two tables:

users
-----
userid (varchar)
password (varchar)
 
user_groups
-----------
userid (varchar)
group (varchar)
 

Note that the database stores groups, not roles. Roles are an app server concept.

We wish to authenticate users against these database tables. To do so in Orion requires the following:

Creating Roles

Define your roles in web.xml and application.xml. Roles in web.xml are local, in that they only apply to the web module. Roles defined in application.xml are global in that they apply to the entire application. For the purposes of this example, we will assume that we have 3 roles, 'guest', 'user', and 'admin'
So in application.xml:

 <security-role>
  <role-name>guest<role-name>
  <description>Guest Users</description>
 </security-role>
 <security-role>
  <role-name>user</role-name>
  <description>Registed Users</description>
 </security-role>
 <security-role>
  <role-name>admin</role-name>
  <description>Admin Users</description>
 </security-role>
 

The J2EE spec specifies also that exact same xml fragment has to go into web.xml, to specify the roles available to the app. The description of the roles will be inherited from that specified in application.xml, but can be overridden within the module.

Installing the User Manager

First lets configure the user manager, this involves registering the DataSourceUserManager with the application, and passing various properties. The properties are used to connect to the database and to determine which tables and columns should be queries.
orion-application.xml:

 <user-manager class="com.evermind.sql.DataSourceUserManager">
  <property name="groupMembershipGroupFieldName" value="group" />
  <property name="groupMembershipUsernameFieldName" value="Userid" />
  <property name="table" value="users" />
  <property name="passwordField" value="password" />
  <property name="groupMembershipTableName" value="user_groups" />
  <property name="usernameField" value="userid" />
  <property name="dataSource" value="<your data source>" />
 </user-manager>
 

The function of any given property is fairly obvious from its name (for example, usernameField is the name of the user id column in the users table). Consult the javadocs for DataSourceUserManager for a detailed breakdown of these properties.

Configuring groups

You might have noticed that there are no properties above for configuring a 'groups' table, so there is no way for the DataSourceUserManager to look up groups (outside of checking the join table), so we need to inform our user manager of the groups that are available. This can be done by adding the groups to principals.xml (application-specific principals.xml, which sits alongside orion-application.xml)
Add the following to your application's principals.xml file:

 <groups>
  <group name="guest" />
  <group name="user" />
  <group name="admin" />
 </groups>
 

Note that this works even though it isn't passed directly to the DataSourceUserManager because of Orion's concept of user manager hierarchy. Any given user manager in Orion can optionally have a parent user manager. The user manager can then choose to delegate some of its calls to its parent user manager and allow it to handle them. The DataSourceUserManager for example has the default user manager (XMLUserManager) as its parent, and delegates the getGroup(String name) method to it. So, by specifying groups in principals.xml, DataSourceUserManager is able to query group information through it's parent (which reads principals.xml).

The logic behind leaving groups out of the DataSourceUserManager is that groups are not 'large data', the list of groups is often small and very rarely is dynamic and changeable enough to merit being managed within a database. Of course, if your particular application is one of those rare ones where you have a large group list that is dynamic, then it's trivial to subclass DataSourceUserManager and override the getGroup method to query your database.

Mapping roles to groups

Lets recap, so far we've defined our application-specific roles, and registered a custom user manager that queries our database tables for users and groups. We've also informed the user manager of all the groups that a user could potentially belong to. The next (and final!) step is to tie the roles and groups together, so that the roles we defined in the first step map to groups stores in the database.
This is done in orion-application.xml, through specifying security role mappings. The following lines need to be added to orion-application.xml:

 <security-role-mapping name="guest">
  <group name="guest" />
 </security-role-mapping>
 <security-role-mapping name="user">
  <group name="user" />
 </security-role-mapping>
 <security-role-mapping name="admin">
  <group name="admin" />
 </security-role-mapping>
 

Note that even though (for simplicity's sake) the above example has a 1-1 mapping of roles to groups, this does not have to be the case. Role to group mappings can be many to many. For example, it is possible to specify that a user in the 'guest' role is any user in the 'user' and 'admin' groups too. Thus ensuring that users in the user and admin groups also have 'guest' privileges.

Also, if there's a group with a given role name, then the 1-1 mapping above is performed automatically by Orion. it is listed above for completeness' sake.

Copyright © 2007 IronFlare AB