Category Archives: Authentication

Custom Tags in JSF 2.0 for Shiro Authorization

Apache Shiro provide JSP Tag library. In JSP, I could use Shiro provided custom tag to determine show/hide html elements based on user’s permission. However, the private project I am working on, I use JSF with facelets and this gives me a dilemma.

  • JSP tag doesn’t meet the JSF lifecycle, so JSP tag from Shiro doesn’t work.
  • I need a conditional statement in the faclets (XHTML). Something like “If user has a permission, display this link. If user doesn’t have a permission, don’t display the link.”
  • Adding a conditional statement in the managed bean doesn’t help because I need to control the logic in the GUI rather than controller layer.
  • Applying security constraints in the web.xml do not help. It helps to prevent unauthorized navigation based on the role, but does not prevent users from clicking the link in the facelet.
  • I thought about implementing permission logic in the managed beans and add conditional statement in the faces-config.xml to navigate different pages based on the permission logic. However, similar to above reason, it is not the solution that I want to have.

Shiro doesn’t have official JSF custom tag support yet. However, I found Deluan’s blog where he created custom tag library for Shiro. His custom JSF 2.0 tag solves the issues that I have in the facelet.

To understand the JSF custom tag, I took a look at the several web sites that explains the JSF custom tag. To summarize my understanding,

  • Most of the custom tags are the UI component related custom tags.
  • Create a custom tag in an XHTML format.
  • Define custom tag details in a tag library.
  • Register the tag library in web.xml.

Above steps are fairly simple and many examples can be found in the  web.

For custom JSF tag, I followed Deluan’s code and simplify several things. Also, based on existing Shiro’s JSP tags, kept the same tag name.

  • Except Principal tag, all other tags doesn’t not need to return any UI output. For me this statement clarifies many things. Below three methods that need to be overridden.
    • encodeAll() –  If this component returns true from isRendered(), render this component and all its children that return true from isRendered(), regardless of the value of the getRendersChildren()flag.
    • saveState() – Invoked after the render phase has completed, this method returns an object which can be passed to the restoreState of some other instance of UIComponentBase to reset that object’s state to the same values as this object currently has.
    • restoreState() – Invoked in the “restore view” phase, this initialises this object’s members from the values saved previously into the provided state object.
    • For a custom component, it is recommended that I should focus on Restore View and Render Response which are the beginning and the end process. See JSF Lifecycle.
  • For other permission view control tags, they are extended from TagHandler. These classes returns true/false based on the Shiro’s SecurityUtils methods. E.g. isPermitted().
  • Define custom tag details in the tag library : shiro-face.taglib.xml. See below.
<tag>
 <tag-name>principal</tag-name>
  <component>
   <component-type>tag.PrincipalTag</component-type>
  </component>
<attribute>
 <description></description>
 <name>type</name>
 <required>false</required>
</attribute>
<attribute>
 <description></description>
 <name>property</name>
 <required>false</required>
</attribute>
<attribute>
 <description></description>
 <name>defaultValue</name>
 <required>false</required>
</attribute>
</tag>
<tag>
<tag-name>hasPermission</tag-name>
<handler-class>tag.HasPermissionTag</handler-class>
<attribute>
 <description></description>
 <name>name</name>
 <required>true</required>
</attribute>
</tag>
  • Define below custom UI component in face-config.xml.
<component>
 <component-type>tag.PrincipalTag</component-type>
 <component-class>tag.PrincipalTag</component-class>
</component>
  • At last, add custom tag library in the web.xml
<context-param>
  <param-name>javax.faces.FACELETS_LIBRARIES</param-name>
  <param-value>/WEB-INF/shiro-face.taglib.xml</param-value>
</context-param>

Usage of Shiro custom tag in the JSF.

<html xmlns="http://www.w3.org/1999/xhtml"
xmlns:f="http://java.sun.com/jsf/core"
xmlns:h="http://java.sun.com/jsf/html"
xmlns:ui="http://java.sun.com/jsf/facelets"
xmlns:shiro="http://xproject.flightCenter/tag">
...
<shiro:hasPermission value="navigation:viewCities">
 <li><h:link value="Cities" outcome="viewCities.xhtml"/></li>
</shiro:hasPermission>

Basically above tag means that if this user has a Permission in following actions (navigation:viewCities:*).  Shiro defines behavior or actions in three sections; domain, action, instance. For Shiro’s permission, go here.

Summary

I encounter a need to have a facelet tag to determine if a user has a permission to navigate to certain page. Shiro provides only JSP tag library and Deluan’s blog provides custom JSF tag for Shiro. I tried to understand his code and eventually used in my XProject Facelet pages. In order to understand the whole process, I needed to understand,

  • Shiro Permission
  • Making custom tag in JSF
  • JSF lifecycle

Apache Shiro Basic 2

This is Stuff” blog explains the Shiro in very detail way.

I can use default filter (authc – in this case), but I can create a custom filter by extending the existing default filters. So no need to update web.xml rather shiro.ini file need to be updated.

 public class VerboseFormAuthFilter extends FormAuthenticationFilter
 {
    protected void setFailureAttribute( ServletRequest request, AuthenticationException ae)
    {
      String message = ae.getMessage();
      request.setAttribute(getFailureKeyAttribute(), message);
    }
 }

 

# Replace Form Authentication filter with Verbose filter. By default, it was "FormAuthenticationFilter".
authc = VerboseFormAuthFilter
# Request parameter with login error info. By default, 'shiroLoginFailure'. This will be used in JSP to retrieve error.
authc.failureKeyAttribute=myShiroLoginFailure

The purpose of having my own Form filter is to display an error message from the filter. As I defined failureKeyAttribute name “myShiroLoginFailutre” in the shiro.ini, same attribute name will be used in the JSP.

<%
String error = (String)request.getAttribute(“myShiroLoginFailure”);
if (error != null)
{
%>
Login attempt was unsuccessful :<%=error%>
<%
}
%>

Apache Shiro Basic – Glassfish, JSF, Eclipse

Apache Shiro is originally called jsecurity. At our work, we use JAAS with Weblogic specific implementation by using LDAP realm. In the xproject, I’d like to implement the Apache Shiro. Shiro documentation was pretty good and several blogger posted pretty detail step by step guide.

In this blog, I’d like to focus on setting up Shiro in JSF project in Eclipse environment with Glassfish. I will focus on the basic authentication & configuration in this page. Later, I will add more roles and SSL connection.

Follow below steps to setup the project:

  1. Download Shiro Web and Shiro Core (1.2.0) from Apache Shiro site.
  2. Create a Dynamic Web Project in the Eclipse. Use MyEclipse implmentation.
  3. Overwrite faces-config.xml to overwrite mojaar implmentation. Please see my previous page.
  4. Create index.xhtml, result.xhtml, and login.jsp.
  5. Create welcome.java as a ManagedBean. navigate() method will return “result.xhtml”. I am omitting all the business logic for the simplicity.
  6. Create shiro.ini file in the WEB-INF folder. Follow the template from Apache Shiro configuration document.
  7. Update web.xml to add Shiro listener, filter, and filter mapping.
  8. I think Shiro source code has references to log4j and slf4j. For this reason, I had to include log4j-1.2.16.jar, slf4j-api-1.6.4.jar, and slf4j-log4j12-1.6.4.jar in the classpath. If Eclipse still throws ClassNotFoundException, incluse these jar files in the lib folder under WEB-INF.

shiro.ini

[main]
authc.loginUrl = /login.jsp
authc.successUrl = /faces/index.xhtml

[users]
user01 = user01, Users
user02 = user02, Users

[roles]
Users = *

[urls]
login.jsp = authc
/** = authc

web.xml add below lines

<listener>
    <listener-class>org.apache.shiro.web.env.EnvironmentLoaderListener</listener-class>
</listener>
<filter>
    <filter-name>ShiroFilter</filter-name>
    <filter-class>org.apache.shiro.web.servlet.ShiroFilter</filter-class>
</filter>
<filter-mapping>
    <filter-name>ShiroFilter</filter-name>
    <url-pattern>/*</url-pattern>
    <dispatcher>REQUEST</dispatcher>
    <dispatcher>FORWARD</dispatcher>
    <dispatcher>INCLUDE</dispatcher>
    <dispatcher>ERROR</dispatcher>   
</filter-mapping>

login.jsp

<form name="loginform" action="" method="post">
    Username: <input type="text" name="username"/><br/>
    Password: <input type="password" name="password"/>
    <input type="checkbox" name="rememberMe" value="true"/>Remember Me?<br/>
   <input type="submit" name="submit" value="Login">
</form>

By hitting http://localhost:8080/MyProject/faces/index.xhtml page, Shiro filter will intercep the request object and redirect to http://localhost:8080/MyProject/login.jsp for authentication.

I added only one role [Users] with two users [user01, user02] in the shiro.ini file for the initial testing purpose, but I can add more roles and define detail navigation rules in the shiro.ini file.

In my next post, I will add more roles and attempt to do with the SSL.