Torque Security Service

This is an implementation of a Security Service which uses Torque generated peers to access the required security information.

Older versions of the Security Service used hard coded Peers to access the security information. The current version can access arbitrary peers to retrieve the information and can be adapted to a pre-existing schema and use peer classes from outside Turbine.

Configuring the Security Service

You need to configure Turbine to use the Torque Security Service:

services.SecurityService.classname = org.apache.turbine.services.security.torque.TorqueSecurityService

You must also tell the Security Service to use the Torque UserManager implementation:

services.SecurityService.user.manager = org.apache.turbine.services.security.torque.TorqueUserManager

See the Security Service page for details of these and other properties that may also need to be configured.

Using the supplied Peer classes

When you start with the Security Service, you should use the Turbine supplied Peer classes to familiarize yourself with the workings of the Torque Security Service. Once you understand how the peer classes are accessed, you can customize to your own Peer classes. Turbine supplies the following peer classes and objects to retrieve data:

Object typeFunctionClass
UserImplementationorg.apache.turbine.services.security.torque.TorqueUser
Peerorg.apache.turbine.services.security.torque.om.TurbineUserPeer
Persistent objectorg.apache.turbine.services.security.torque.om.TurbineUser
GroupImplementationorg.apache.turbine.services.security.torque.TorqueGroup
Peerorg.apache.turbine.services.security.torque.om.TurbineGroupPeer
Persistent objectorg.apache.turbine.services.security.torque.om.TurbineGroup
RoleImplementationorg.apache.turbine.services.security.torque.TorqueRole
Peerorg.apache.turbine.services.security.torque.om.TurbineRolePeer
Persistent objectorg.apache.turbine.services.security.torque.om.TurbineRole
PermissionImplementationorg.apache.turbine.services.security.torque.TorquePermission
Peerorg.apache.turbine.services.security.torque.om.TurbinePermissionPeer
Persistent objectorg.apache.turbine.services.security.torque.om.TurbinePermission
If you retrieve objects from the Torque Security Service, you will always get the object classes in the "Implementation" rows. The Torque Security Service will use the peers described in the "Peer" rows and internally the implementation objects will use the objects from the "Persistent" rows. As you will see later, you can reconfigure the "Peer" and "Persistent" objects.

Turbine supplied table schema

The Peers and objects supplied with the Torque Security Service were generated from a Torque Schema. Its definition is shown here.

Turbine uses the following configuration for accessing the Torque schema. If you just want to use the default Peers, you don't need any of the following configuration, these are the defaults:


# This is the Peer class used to access the user peer (org.apache.turbine.services.security.torque.om.TurbineUserPeer)
services.SecurityService.torque.userPeer.class = org.apache.turbine.services.security.torque.om.TurbineUserPeer

# The columns in the peer used to retrieve information. These are the names of the constants
# in the configured peer
services.SecurityService.torque.userPeer.column.name       = LOGIN_NAME
services.SecurityService.torque.userPeer.column.id         = USER_ID
services.SecurityService.torque.userPeer.column.password   = PASSWORD_VALUE
services.SecurityService.torque.userPeer.column.firstname  = FIRST_NAME
services.SecurityService.torque.userPeer.column.lastname   = LAST_NAME
services.SecurityService.torque.userPeer.column.email      = EMAIL
services.SecurityService.torque.userPeer.column.confirm    = CONFIRM_VALUE
services.SecurityService.torque.userPeer.column.createdate = CREATED
services.SecurityService.torque.userPeer.column.lastlogin  = LAST_LOGIN
services.SecurityService.torque.userPeer.column.objectdata = OBJECTDATA

# These are the objects returned by the configured user peer (org.apache.turbine.services.security.torque.om.TurbineUser)
services.SecurityService.torque.user.class = org.apache.turbine.services.security.torque.om.TurbineUser

# These bean properties are queried from the returned object to retrieve the 
# information
services.SecurityService.torque.user.property.name         = UserName
services.SecurityService.torque.user.property.id           = UserId
services.SecurityService.torque.user.property.password     = Password
services.SecurityService.torque.user.property.firstname    = FirstName
services.SecurityService.torque.user.property.lastname     = LastName
services.SecurityService.torque.user.property.email        = Email
services.SecurityService.torque.user.property.confirm      = Confirmed
services.SecurityService.torque.user.property.createdate   = CreateDate
services.SecurityService.torque.user.property.lastlogin    = LastLogin
services.SecurityService.torque.user.property.objectdata   = Objectdata

# This is the Peer class used to access the Group Peer (org.apache.turbine.services.security.torque.om.TurbineGroupPeer)
services.SecurityService.torque.groupPeer.class = org.apache.turbine.services.security.torque.om.TurbineGroupPeer

# The columns in the peer used to retrieve information. These are the names of the constants
# in the configured peer
services.SecurityService.torque.groupPeer.column.name      = GROUP_NAME
services.SecurityService.torque.groupPeer.column.id        = GROUP_ID

# These are the objects returned by the configured group peer (org.apache.turbine.services.security.torque.om.TurbineGroup)
services.SecurityService.torque.group.class = org.apache.turbine.services.security.torque.om.TurbineGroup

# These bean properties are queried from the returned object to retrieve the 
# information
services.SecurityService.torque.group.property.name        = Name
services.SecurityService.torque.group.property.id          = GroupId

# This is the Peer class used to access the Role Peer (org.apache.turbine.services.security.torque.om.TurbineRolePeer)
services.SecurityService.torque.rolePeer.class = org.apache.turbine.services.security.torque.om.TurbineRolePeer

# The columns in the peer used to retrieve information. These are the names of the constants
# in the configured peer
services.SecurityService.torque.rolePeer.column.name       = ROLE_NAME
services.SecurityService.torque.rolePeer.column.id         = ROLE_ID

# These are the objects returned by the configured role peer (org.apache.turbine.services.security.torque.om.TurbineRole)
services.SecurityService.torque.role.class = org.apache.turbine.services.security.torque.om.TurbineRole

# These bean properties are queried from the returned object to retrieve the 
# information
services.SecurityService.torque.role.property.name         = Name
services.SecurityService.torque.role.property.id           = RoleId

# This is the Peer class used to access the Permission Peer (org.apache.turbine.services.security.torque.om.TurbinePermissionPeer)
services.SecurityService.torque.permissionPeer.class = org.apache.turbine.services.security.torque.om.TurbinePermissionPeer

# The columns in the peer used to retrieve information. These are the names of the constants
# in the configured peer
services.SecurityService.torque.permissionPeer.column.name = PERMISSION_NAME
services.SecurityService.torque.permissionPeer.column.id   = PERMISSION_ID

# These are the objects returned by the configured permission peer (org.apache.turbine.services.security.torque.om.TurbinePermission)
services.SecurityService.torque.permission.class = org.apache.turbine.services.security.torque.om.TurbinePermission

# These bean properties are queried from the returned object to retrieve the 
# information
services.SecurityService.torque.permission.property.name   = Name
services.SecurityService.torque.permission.property.id     = PermissionId

The column names and the bean properties do not always match, because you can change the name of the bean property with the javaName attribute in the Torque XML file.

If you omit the class definition of the object classes (torque.user.class, torque.group.class, torque.role.class, torque.permission.class), the bean property OMClass in the peer is consulted which should return the default class that this peer returns.

Configuring Torque Security Service to use your own peer classes

The most interesting application for this is to extend some of the tables with more columns for additional data. In this example, the User table gets extended by two more columns called "TELEPHONE" and "FAX".

At first we create a new torque schema:

  <table name="CUSTOM_USER" idMethod="idbroker">
    <column name="USER_ID" required="true" primaryKey="true" type="INTEGER"/>
    <column name="LOGIN_NAME" required="true" size="64" type="VARCHAR" javaName="UserName"/>
    <column name="PASSWORD_VALUE" required="true" size="16" type="VARCHAR" javaName="Password"/>
    <column name="FIRST_NAME" required="true" size="64" type="VARCHAR"/>
    <column name="LAST_NAME" required="true" size="64" type="VARCHAR"/>
    <column name="EMAIL" size="64" type="VARCHAR"/>
    <column name="CONFIRM_VALUE" size="16" type="VARCHAR" javaName="Confirmed"/>
    <column name="MODIFIED" type="TIMESTAMP"/>
    <column name="CREATED" type="TIMESTAMP" javaName="CreateDate"/>
    <column name="LAST_LOGIN" type="TIMESTAMP"/>
    <column name="OBJECTDATA" type="VARBINARY"/>

    <column name="TELEPHONE" size="32" type="VARCHAR" javaName="Phone" />
    <column name="FAX" size="32" type="VARCHAR"/>

    <unique>
        <unique-column name="LOGIN_NAME"/>
    </unique>        

Note a few things:

  • This schema is the same as the TURBINE_USER schema from Turbine with the addition of two columns. This is especially important with regard to the "javaName" attributes which configure the name of the property for this column in the persistent objects.
  • The "TELEPHONE" column has its property name set to "Phone".

The Torque schema now gets translated into two java classes: CustomUserPeer for accessing the tables and CustomUser as objects returned by the Peer.

Now we configure the Torque Security Service to for using this peer as UserPeer:

# This is the Peer class used to access the user peer (org.apache.turbine.services.security.torque.om.TurbineUserPeer)
services.SecurityService.torque.userPeer.class = CustomUserPeer

Please note that we neither configure any column or property properties nor do we configure services.SecurityService.torque.user.class. So the Torque Security Service will query the CustomPeer for the class of the returned objects. Now Turbine uses your supplied Custom User Peer for querying User information. However you can't access your custom columns (yet)...

Accessing your custom columns can be done in two ways. A simple and a complex:

The simple way:

   User user = TurbineSecurity.getUser("test");

   String phone = ((CustomUser) (((TorqueUser) user).getPersistentObj())).getPhone();

   /*  Better readable: */

   User         u2  = TurbineSecurity.getUser("test2");
   TorqueUser   tu2 = (TorqueUser) u2;
   CustomUser   cu  = (CustomUser) u2.getPersistentObj();
   String fax       = cu.getFax();

Ugly, isn't it? If you get a class cast exception somewhere on the way, don't worry. Then you misconfigured either the Torque Security Service (CCE when doing tu2 = (TorqueUser) u2) or the peer (CCE when doing cu = (CustomUser) u2.getPersistentObj()).

The elegant way:

public class ExtendedUser extends TorqueUser
{
  public ExtendedUser()
  {
      super();
  }

  public ExtendedUser(Persistent obj)
  {
      super(obj);
  }

  public String getPhone()
  {
    return ((CustomUser) getPersistentObj()).getPhone();
  }

  public void setPhone(String phone)
  {
    ((CustomUser) getPersistentObj()).setPhone(phone);
  }

  public String getFax()
  {
    return ((CustomUser) getPersistentObj()).getFax();
  }

  public void setFax(String fax)
  {
    ((CustomUser) getPersistentObj()).setFax(fax);
  }
}

TurbineResources.properties:

services.SecurityService.user.class = ExtendedUser

And then:

ExtendedUser eu = (ExtendedUser) TurbineSecurity.getUser("test");
String phone = eu.getPhone();

Advanced customization

Consider the following schema:

<table name="CUSTOM_ROLE" idMethod="idbroker">
  <column name="CUSTOM_ID"    required="true" primaryKey="true" type="INTEGER"/>
  <column name="NAME_OF_ROLE" required="true" size="64" type="VARCHAR"/>

  <unique>
      <unique-column name="NAME_OF_ROLE"/>
  </unique>
  
</table>

If you want to use this as the role peer, you can configure the Torque Security Service like this:

services.SecurityService.torque.rolePeer.class = CustomRolePeer

# The columns in the peer used to retrieve information. These are the names of the constants
# in the configured peer
services.SecurityService.torque.rolePeer.column.name       = NAME_OF_ROLE
services.SecurityService.torque.rolePeer.column.id         = CUSTOM_ID

# These are the objects returned by the configured role peer (org.apache.turbine.services.security.torque.om.TurbineRole)
services.SecurityService.torque.role.class = CustomRole

# These bean properties are queried from the returned object to retrieve the 
# information
services.SecurityService.torque.role.property.name         = NameOfRole
services.SecurityService.torque.role.property.id           = CustomId

Of course you must assure that the necessary foreign key relations in the database are still valid. With some databases, e.g. MySQL this is not a big concern, because they don't support foreign keys at all.