Jaffa Logo
 
SourceForge.net
Home Contact Us FAQs Site Map
Source Forge: Homepage Bugs @ Sourceforge Mailing Lists @ Sourceforge Task Manager @ Sourceforge CVS @ Sourceforge
Jaffa Site
Jaffa Runtime
Jaffa RAD
Sub-Projects
Security / Applicationorg.jaffa.security

Overview

This document details the Application Security architecture implemented in the Jaffa such that any application using this framework can take advantage of this feature.

Introduction

Jaffa has three important configuration files used to model security (components.xml, business-functions.xml and roles.xml). To build an application that uses the Application Security framework these files must be set up to model the security rules of the application.

Below shows the basic overview of the JAFFA descriptors, each one being defined in its own XML file

Click on image for larger view

The rest of the document will explain the three different types of security which can be used via the Jaffa framework and some sample code.

Notes On Modeling

The Security model is design to reflect the use-case model, but there are two ways to approach this mapping. In a use case model we can have inheritance of actors, this implies that an actor that extends another also has all the privileges of the actor they extend.

For example we take the example of a manager extends the supervisor, which extends the clerk. At each level this actor has more access to functions in the system (use-cases!). The decision becomes when you want to map real users to roles. To create a user who is a manager do you give them access to the 'Manager' role, or access to the "Manager,Supervisor and Clerk" Roles.

The assumption we have made in our design, and in the Together Modeling Plug in, is that in the above case the role clerk has access to some functions, and then the supervisor role is only defined to have access to the extra functions beyond what the clerk has, and likewise the Manager role only has access to the addition functions that the supervisor or clerk does not have. In this case to give a user access to the full set of manager functions they must be defined to have access to the roles "Manager,Supervisor,Clerk".

We chose this approach as it allows the architecture to combine the roles and deal with inheritance, and it keeps true to the encapsulation of inherited roles, just like object inheritance. If you prefer the other way, you'll need to invent a way to 'denormalize' the current roles.xml file, so inherited function are explicitly defined in each role that inherits another.

Role-based Security

The concept for role-based security is that a role represents a profile of what a user can do. These roles will govern access to components and business functions. As many users of a system perform the same roles, users will be assigned to roles. In this way the need for setting up a security profile for each specific user is greatly reduced. A role can be defined for each ‘Actor’ that is using the system, and each user will represent an instance of a particular actor.

In the use-case model, just as an actor can inherit from other actors, a user can be associated with multiple roles. We may have a Clerk Role, and a Manager Role, and a Paul may be assign the Clerk role, where as John, the manager may be assigned the Clerk and Manager Roles as he can play in both roles.

The reason for ‘declarative’ security roles is to add flexibility to the application. A role is a notional thing and many organizations want to define their roles in different ways with different levels of granularity. From a use-case modeling perspective, this is like developing the use-cases, and then at application implementation time allow the actor hierarchy to be defined for a specific implementation of the application. This implies that the software should not be coded to make decisions based on specific actors, or roles, it should use an abstract programming model that could then be used to defined the scope of these roles

For this reason the architecture should assume that roles will be modified (create, update, delete) while the application is operational.

Component Based Security

Jaffa is based on a ‘component’ architecture, each component relates to all or part of a use-case. For a given role we need to be able to decide whether this component should be available. If a component is not available the security system should not allow the user to execute that component.

It should be possible to ascertain whether or not a user has access to a given component prior to executing it so that it could be removed from the user’s view. This capability will be essential is a menu based user interface is to be used by the application, which should hide access to components based on the users security.

Business Function Security

In addition to component security, many applications need to control access to various functions at a much lower level. This level of access will be referred to as ‘Business Function’ level access. A business function can be as small as a single line of code, or may represent a complete set of use cases. It is entirely up to the scope of the application using Jaffa framework.

Again based on the abstract nature of the layered architecture, this ‘guarded’ business function maybe something in a domain object, service class, transaction controller, component controller or even an action class.

The main principle is that a set of code will be encapsulated by a named business function, and the encapsulated code will only be executable if the role of the current user grants access to this business function

Writing Secured Web Pages with Jaffa

With Jaffa's Tag Library we provide two ways to guard the generation of HTML content, either by individual business function access, or by component access (which is based on access to all the mandatory functions for that component). The two tags can be either to display the contained HTML based on either access, or no-access to the specified function or component.

These guards are heavily used arround buttons which link to the execution of related components such that the button is hidden if you don't have access to the component it executes.

For more details look at the Tag Library referece guide

Writing Secured Code with Jaffa

This section explains how to use the Jaffa Security Model into your application to guard different functions (business-functions) based on role-based access. It also explains how to handle component access based on the business function access. There also some sample code explaining the same.

  • The following code shows how to guard a function and throws an exception from the secured method.
        public FormKey do_Button1b_Clicked() {
            System.out.println("Trying to do something protected by Function1");
            try {
                SecurityManager.runFunction("Function1", new PrivilegedExceptionAction()
                {
                    public Object run() {
                        throw new UnsupportedOperationException("Test Exception");
                    }
                });
            } catch (AccessControlException e) {
                   ((Page1Form)form).setMessage("You were not allowed access to Function1");
            } catch (PrivilegedActionException e) {
                ((Page1Form)form).setMessage("Caught Exception From Secured Function : " +
                    e.getException().getClass().getName() + " - " + e.getException().getMessage());
            }
            return new FormKey(Page1Form.NAME, component != null ? component.getComponentId() : null);
        }
    

  • The following code handles the fact that security access is denied.
        public FormKey do_Button2_Clicked() {
            System.out.println("Trying to do something protected by Function2");
            try {
                SecurityManager.runFunction("Function2", new PrivilegedAction()
                {
                    public Object run() {
                        String msg = "Doing Something Protected By Function2";
                        ((Page1Form)form).setMessage(msg);
                        System.out.println(msg);
                        return null;
                    }
                });
            } catch (AccessControlException e) {
                String msg = "You Were Not Allowed Access To Function 2";
                ((Page1Form)form).setMessage(msg);
                System.out.println(msg);
            }
            return new FormKey(Page1Form.NAME, component != null ? component.getComponentId() : null);
        }
    

  • The following code tries to run a component that the user may, or may not have access to
        public FormKey do_Button3_Clicked() {
            System.out.println("Trying to run component Test.Security.Test2");
            try {
                IComponent c = ComponentManager.run("Test.Security.Test2", UserSession.getUserSession(request) );
                String msg = "Running Component : Create Succeeded";
                ((Page1Form)form).setMessage(msg);
                System.out.println(msg);
            } catch (AccessControlException e) {
                String msg = "No Access To Component";
                ((Page1Form)form).setMessage(msg);
                System.out.println(msg);
            } catch (ComponentCreationRuntimeException e) {
                String msg = "Running Component : Create Failed";
                ((Page1Form)form).setMessage(msg);
                System.out.println(msg);
            }
            return new FormKey(Page1Form.NAME, component != null ? component.getComponentId() : null);
        }
    
Configuring XML descriptors

As mentioned earlier the three configuration files needed to model security are roles.xml, business-function.xml and components.xml. This section explains how you can configure the three xml files.

Note: Here we take the example of the UserMaintenance in SampleApp

Scenario: A ClientUser (role) does not have access to UserMaintenance while an Administrator has access to UserMaintenance. First of all , a component definition is defined in components.xml

Components.xml
<component id="User.UserMaintenance">
    <class>org.jaffa.applications.sample.modules.user.components.usermaintenance.ui.UserMaintenanceComponent</class>
   <type>Skeleton</type>
   <mandatory-function name="User.User.Maintenance"/>
</component>

Then a business function is defined in business-function.xml which is mentioned in components.xml

Busniess-Function.xml
<business-function name="User.User.Maintenance">
    <description>Create/Modify User Account</description>
</business-function>

Then the roles.xml is defined specifying which user/role has access to the business function.

Roles.xml
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE roles PUBLIC "-//JAFFA//DTD Security Roles 1.0//EN"
                   "http://jaffa.sourceforge.net/DTD/security-roles_1_0.dtd">
<roles>
   <role name="User">
       <description>This is a User. Every other user needs to inherit from this User</description>
       <grant-function-access name="User.User.SelfUpdate"/>
   </role>
   <role name="Client">
       <description>This is a Client user</description>
    <include name="User"/>
       <grant-function-access name="User.User.Inquiry"/>
       <grant-function-access name="User.User.Details"/>
   </role>
   <role name="Administrator">
       <description>This is an administrator</description>
    <include name="Client"/>
       <grant-function-access name="User.User.Maintenance"/>
       <grant-function-access name="User.User.Inquiry"/>
       <grant-function-access name="User.User.Details"/>
   </role>
</roles>

Note that the business function User.User.Maintenance is defined only for Administrator

You can alternatively generate these xml files from a UML model, (if you have the Together Control Center) using the Jaffa Security Plug in

Now, In addition to this we should guard this function in the transaction controller.

The code in transaction controller looks something like this. (Full source available in CVS)

private boolean hasMaintenanceAccess() {
   return hasAccess("User.User.Maintenance");
}
private boolean hasAccess(String functionName) {
   boolean access;
   try {
       SecurityManager.runFunction(functionName, new PrivilegedAction() {
           public Object run() {
               return null;
           }
       });
       access = true;
   } catch(Exception e) {
       access = false;
   }
   return access;
}

And in the create function for UserMaintenance you would use it like this.

   // ensure that the user has access to the business function - User.UserDetail.Maintenance
   if (!hasMaintenanceAccess()) {
       String str = "Create aborted. User has no access to the Business Function: 'User.User.Maintenance'";
       log.error(str);
       aes.add(new UserMaintenanceException(UserMaintenanceException.PROP_NO_MAINT_ACCESS));
       throw aes;
   }

Includes and Excludes

New in v1.2 of Jaffa is two extra tags inside a role definition. These are <includes> and <excludes>. This are generated by the Together Security Plug-In (or can be created manually).

<includes>

If a role inherits from another role, then an <includes> tag is put in <role> tag. It is possible that a role can include multiple, or that and included role itself, includes other roles.

The jaffa security model does not use this information directly, but makes it available via its security API's. This can then be used to validate that a user has selected a valid set of roles bases on these rules. If you look at the UserMaintenace component in the sample app, you can see this in action.

<excludes>

If a role is mutually exclusive with other roles, then an <excludes> tag is put in <role> tag. For example in a supply chain system you could have the roles, Supplier, Buyer and Customer, to represent a three part supply chain, where you can only be one of these. In this case a each role, would be defined to exclude the other two.

Again, the UserMaintence component in the sample app will use this information to validate the list of Roles selected for a user, and throw a validation error if any mutually exclusive role combination is selected.


File: index.html, Last Modified: Mon Jul 14 2003 at 3:12:34pm. This site has been built using PPWIZARD