Custom Role Filters with Bootique Shiro Web

In this post we're going to discuss adding a custom Role Filter to Bootique Shiro Web. We'll be using my Bootique Shiro Demo app on GitHub for the source code.

The Issue

User Ken, who is assigned the user role is currently logged-in. He attempts to load the /admin page but it is accessible only to users with the admin role. The Shiro Web Authorization Filter looks for an unauthorizedUrl property in Shiro.ini so it can redirect to that page. If that property is missing it throws a 401 Unauthorized Response and we get an ugly unhandled error on our web page.

You see, we do not use a Shiro.ini with Bootique and cannot currently set the Shiro Web unauthorizedUrl property in bootique.yml or elsewhere. At least I haven't cracked that one yet and that's perfectly fine. We can create our own Roles Authorization Filter and enter any unauthorizedUrl property we like.

The Shiro DefaultFilter Enumerator

This may seem a weird time to bring an Enumerator into the discussion, but we want to mention the Shiro DefaultFilter Enumerator as it lists the Shiro Filters we can customize with Bootique. One of those Filter Constants is roles. This is what we will use to add our Custom Filter to the Bootique Shiro Web Module in our main module config().

ShiroWebModule.extend(binder).setFilter("roles", NixmashRoleFilter.class);

Now our app will run our roles Filter and not the Shiro Web Default roles Filter.

Why a Roles Filter?

If you look at the Shiro Default Filter Constants you may wonder why we're creating a roles Filter and not a perms filter or authc or whatever. We're creating a roles Filter because of the condition on the /admin path, which in our Bootique.yml looks like this.

The Custom NixmashRolesFilter

Our Roles Filter is named NixmashRolesFilter and it extends the Shiro Web RolesAuthorizationFilter class. Here it is in its entirety. Not a lot of code, as our only goal here is to set an unauthorizedUrl property and override the onAccessDenied() method.

There, no more ugly 401 Response Error!

Source Code Notes for this Post

Source code discussed in this post is found in my Bootique Shiro Demo app on GitHub.