Apache Shiro tags for Facelets - Securing your JSF pages

| Comments

UPDATE There is now a JSF 2.0 version of this library available in the project repo

First, a small introduction. You can skip it and go straight to the source code, if you want.

I started working with Apache Shiro when it was still called JSecurity, and I have to say that it really rocks! I tried to use Spring Security (Acegi) in some projects, but the easiness and lean approach of Shiro is unbeatable. For a quick introduction, here’s a quote from the project’s site:

Apache Shiro is a powerful and easy-to-use Java security framework that performs authentication, authorization, cryptography, and session management.
With Shiro’s easy-to-understand API, you can quickly and easily secure any application – from the smallest mobile applications to the largest web and enterprise applications.

I’ve used it in Java and Grails projects, and recently I’ve even been experimenting it with Google App Engine. It fits very well in almost any Java platform project that needs security.

Shiro already works great in a JSF/Facelets project. You can use its filters to grant and deny access to some parts of your application and to force authentication (redirect to login).

The only functionality missing is the power of its JSP taglib, that is used to conditionally render some parts of your HTML, based on user’s authorization, roles and permissions (you can learn how to use them with this simple example project). The problem is that this conditional rendering is not totally compatible with JSF’s phases. Better than trying to fit a cube into a spherical hole, I decided to rewrite Shiro’s JSP tags into a Facelets taglib, totally compatible with JSF.

All original tags are available as their Facelets equivalents, and I have introduced two new ones:

<shiro:hasAnyPermission> - Displays body content only if the current user has one of the specified permissions from a comma-separated list of permission strings.

<shiro:remembered> - Displays body content only if the current user has a known identity that has been obtained from ‘RememberMe’ services. Note that this is semantically different from the <shiro:authenticated> tag, which is more restrictive.

I’ve already submitted a patch to Shiro’s development team, but they’re very busy at the moment packaging the new 1.1 version for release. So I decided to share the taglib on GitHub, and host the artifacts in my personal maven repository, as I need to use the tags in an on-going project.

If you want to try it in your maven project, add my repository to your pom.xml:

        <repositories>
                <repository>
                    <snapshots>
                        <enabled>false</enabled>
                    </snapshots>
                    <id>bintray-deluan-maven</id>
                    <name>bintray</name>
                    <url>http://dl.bintray.com/deluan/maven</url>
                </repository>
        </repositories>

and add the jar dependency:

        <dependency>
            <groupId>org.apache.shiro</groupId>
            <artifactId>shiro-faces</artifactId>
            <!-- See the latest version on the project's homepage -->
            <version>2.0</version>
        </dependency>

Now you can declare Shiro’s namespace in your xhtml pages and use the tags like this:

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en"
      xmlns:ui="http://java.sun.com/jsf/facelets"
      xmlns:shiro="http://shiro.apache.org/tags">
<head>
    <title><ui:insert name="titulo">Shiro Faces Test</ui:insert></title>
</head>

<body>
    <p>Hi, <shiro:guest>Guest</shiro:guest>
          <shiro:user><shiro:principal/></shiro:user>!
    </p>
</body>

</html>

That’s it! Just keep in mind that as soon as this lib gets incorporated officially in Shiro, I’ll stop updating it in GitHub and all future enhancements will only be available in the official version. If you want to see the tags incorporated officially into Shiro sooner than later, you can vote here: https://issues.apache.org/jira/browse/SHIRO-206

And if you have any suggestion, please let me know.

Enjoy ;)

Comments