Thursday, June 6, 2013

Authorization in JSF with Facelets View Handler

According to wikipedia, authorization is the function of specifying access rights to resources.
Authorization is important to protect sensitive against different users.

The simplest way is to provide the access right to the targeted fields/components directly
for readOnly access,
<h:outputText id="authorizedId" value="#{bean.authorizedValue}" readonly="#{bean.authorizedReadonly}" />

for viewable access,
<h:outputText id="authorizedId" value="#{bean.authorizedValue}" disabled="#{bean.authorizedDisabled}" />

but the above solution is NOT feasible if there are many pages and fields/components to be authorized;
NOT flexible, if there are access right changes, re-coding is required.

Another feasible way is through FaceletsViewHandler.
In JSF with Facelets view handling, we can actually place all the authorization controls to the FaceletsViewHandler as the control central.
Steps:
1. Create a table to store all the authorization settings with the following info.
view_idcomponent_idroleaccess_typeaccess_right
/mypage.xhtmlmyIdadmin|user|guestreadonly|renderedtrue|false

2. extends the default FaceletsViewHandler
package kian.authorization;
public class AuthorizationViewHandler extends com.sun.facelets.FaceletViewHandler {
     ............
     ............
}

3. override createResponseWriter
@Override
protected ResponseWriter createResponseWriter(FacesContext context)
    throws IOException, FacesException { 
    // 3.1 retrieve authorization data by viewId from database
    // 3.2 in the viewroot, find the target component by componentId
    // 3.3 apply access right to target component.
}

3.1 retrieve authorization data
In this method, write a method to access to persistence layer to retrieve authorization data, and return the data in the form of Map, where componentId is the key, accessRight  list is the value.
Map[ componentId, [access_type, access_right] ]
Map<String, List> accessRightMap = retrieveAuthorizationByViewIdAndRole( context.getViewRoot().getViewId(), userRole );

3.2 find the targeted component in viewRoot.
loop through the viewRoot to find the target component
public UIComponent findComponentById(UIComponent root, String id) {
    UIComponent component = null;
    for (int i = 0; i < root.getChildCount() && component == null; i++) {
        UIComponent child = (UIComponent) root.getChildren().get(i);
        component = findComponentById(child, id);
    }
    if (root.getId() != null) {
        if (component == null && root.getId().equals(id)) {
            component = root;
        }
    }
    return component;
}

3.3 apply the access right
if( accessrightMap.contains( component.getId() ) ) {
    List list = accessrightMap.get( component.getId() );
    if( list.get(0).equals( "readonly" ) ) {
        component.setReadonly( list.get(1) );
    } else if( list.get(0).equals("rendered") ) {
        component.setRendered( list.get(1) );
    }
}

with the above configuration and coding, the access right control is flexible and configurable with the record in the table.
Thus, in future if there are authorization right changes, the only things to do is simply configure the record in the table based on requirements.


Done!!

LinkWithin

Related Posts Plugin for WordPress, Blogger...