April 16, 2008

JSF & Security

This article introduces a Java module which utilizes phase listeners for securing JSF applications.

Feature list:
  • user, password and role based
  • interfaces throughout for independence of concrete implementations
  • easy to integrate into a Spring framework environment
  • supports password and cookie encoding
  • login data can be placed in cookies for automatic user logins
  • a special navigation handler ensures that invalid navigation rules do not open security holes
  • users may be allowed to login to multiple sessions or not

Introduction

The security core is independent of JSF. Thus, it could be used for other view technologies as well as for any view-independent access control. This affects all classes for authentication, authorization, access rules and cryptography.

How does it work ?

We have identities, usually representing application users. Identities are grouped by assigning roles. Access rules define which roles
are required to path through to certain views.
The authenticator is responsible for identifying users, whereas guards process authorization requests and either approve or refuse them.

Guards do not know whether access requests represent web sites or anything else. They just follow their given rules to make decisions.
Thus, other implementations of Guard and Rule are possible, for example to secure single UI components.

The following two classes allow the integration of the security core into JSF:
  • SecurityListener is a phase listener working in the RESTORE_VIEW phase
  • the LoginService is responsible for logins, cookies and creating identities respectively user objects

For denied requests two cases must be distinguished:
  1. The user is not logged in. If so, the loginRequiredNavigation of LoginService returns the new navigation.
  2. The user was logged in or can be logged in automatically. Then,
    • the Guard delivered the violated rule, its errorView is taken as navigation target
    • property defaultErrorNavigation of LoginService represents the fallback for rules without error view

In either case, if no valid target can be obtained or any exception raises, a 403-HTTP error is sent.


Configuration

Sample Spring configuration:




The default navigation handler of JSF is ignorant of invalid navigation rules. Non-existing rule outcomes result in no navigation at all, meaning that view requests which have just been denied, would pass through nevertheless.
The AssertingNavigationHandler takes care of this problem: an InvalidNavigationRuleException is thrown in case of an unknown or maybe just misspelled navigation directive.
<navigation-handler>
   de.voodoosoft.jroots.ui.jsf.core.AssertingNavigationHandler
</navigation-handler>   
(faces-config.xml)

To be able to configure the SecurityListener as Spring bean, the following listener delegate must be installed:
<lifecycle>
   <phase-listener>
      de.voodoosoft.jroots.ui.jsf.core.DelegatingPhaseListenerMulticaster
   </phase-listener>
</lifecycle>
(faces-config.xml)

The DelegatingPhaseListenerMulticaster automatically searches Spring's application context for registered phase listeners like this:
<bean id="securityListener"
   class="de.voodoosoft.jroots.ui.jsf.security.SecurityListener">
   <property name="loginService" ref ="loginService"></property>
   <property name="guard" ref="guard"/>  
   <property name="defaultErrorNavigation" value="login"></property>
</bean>

Download and Example

The complete package jroots-jsf-security.zip with a full working example (folder /examples/example4) and sample Spring configurations can be downloaded here: JRoots Application Bricks

April 4, 2008

Dynamic JSF tables

Here, I like to present a small open source library allowing to dynamically create JSF tables with Java code instead of using JSP tags.
JSP pages tend to get clumsy and not very easy to get at first sight, so we benefit from smaller files, more dynamic views as well as from the decouplement of pages and underlying bean properties.

Features

The required table structure (shown columns) can be put together by manual coding or automatically from processing properties of a given Java bean.
Column labels can be retrieved from assigned resource files.
The concrete component classes used are externally configured, for example with Spring, thus leaving the table factory independent of various JSF libraries and making it possible to switch the UI without complex engagement.
Numeric columns get right aligned by default.

At present there are the following column types:
  • Standard-Text
  • Link
  • Checkbox
  • Drop-Down (<select>-Tag)
  • Image

If these column types are not sufficient, additional individually built columns can be integrated as well.

Packages:
  • de.voodoosoft.jroots.ui.jsf.factory.table
  • de.voodoosoft.jroots.ui.jsf.factory.table.impl
Dependencies:
  • de.voodoosoft.jroots.ui.jsf.core
  • de.voodoosoft.jroots.core.annotations

Example
jroots-example1
(configured with Spring's dependency injection):

What is left inside the JSP is the raw table without columns but with bindings for both the table component and the presented data.
<h:dataTable id="customerList"
   binding="#{customerController.dataTable}"
   value="#{customerController.beanData}"
   var="rowBean">
</h:dataTable>

In order to resolve Spring beans placed in JSP pages, the following configuration is required:

web.xml:
<listener>
   <listener-class>
      com.sun.faces.config.ConfigureListener
   </listener-class>
</listener>

<listener>
   <listener-class>
      org.springframework.web.context.ContextLoaderListener
   </listener-class>
</listener>

faces-config.xml:
<variable-resolver>
   org.springframework.web.jsf.DelegatingVariableResolver
</variable-resolver>

The UI-controller is defined inside Spring'S application context:
<bean id="customerController"
   class="de.voodoosoft.jroots.examples.example2.ui.jsf.customer.CustomerController"
   scope="request">
   <property name="tableFactory" ref="tableFactory"/>
</bean>

Dependency injection is used to assign the used TableFactory to the controller:
public class CustomerController {
    public void setTableFactory(TableFactory factory) {
        this.factory = factory;
    }

    private TableFactory factory;

When JSF asks for the table component, it gets built by the TableFactory:
public class CustomerController {
   public UIData getDataTable() {
      if (dataTable == null) {
         TableDefinition tableDef = factory.buildDefinition(CustomerBean.class);
         dataTable = factory.buildTable(tableDef);
      }

      return dataTable;
   }

The table structure follows the properties of the given bean, in this example name and address:
public class CustomerBean {
   public CustomerBean(String name, String address) {
      this.name = name;
      this.address = address;
   }

   private String name, address;

The second example jroots-example2 demonstrates the usage of RichFaces components instead of the reference implementation. All that has to be done is to modify the application context: properties of tableFactory and columnBuilder get component classes of RichFaces:
<bean id="tableFactory"
   class="de.voodoosoft.jroots.ui.jsf.factory.table.impl.DefaultTableFactory">
   <property name="resourceTag" value="res"/>
   <property name="rowBeanTag" value="rowBean"/>
   <property name="uiDataClass" value="org.richfaces.component.html.HtmlDataTable"/>
   <property name="columnBuilder">
      <map>
         <entry key="de.voodoosoft.jroots.ui.jsf.factory.table.ColumnDefinition" value-ref="defaultColumnBuilder"/>
      </map>
   </property>
</bean>


Finally, the third example jroots-example3 shows generation of link and drop-down columns. There are annotations for both column types. However, there is no need to use those, you can define any column by manual coding as well:
public class Guitar {

   @Link
   private String name;

   @DropDown(targetEntity = Wood.class)
   private Long bodyWood;

   @DropDown(targetEntity = Wood.class)
   private Long neckWood;

Links can either be mapped to controller methods (formSubmit = true) or point to external targets. Link targets are set inside the controller:

Internal Link:
LinkColumnDefinition linkCol = tableDef.getColumn("name");
linkCol.setTarget("#{guitarController.onGuitarClicked}");

External Link:
linkCol = new LinkColumnDefinition("google");
linkCol.setOutput("google");
linkCol.setFormSubmit(false);
linkCol.setTarget("http://www.google.de/search?q=#{guitarController.dataTable.rowData.name}");
tableDef.addColumn(linkCol);
Here we have the characteristic that controller properties are evaluated and passed as URL parameters. To access the current row bean, getRowData() of UIData is invoked in this example.

Spring configuration:



Download:
All the involved jar files
  • jroots-core.jar
  • jroots-jsf-core.jar
  • jroots-jsf-factory.jar
and the presented examples are available for download: voodoosoft