Apache Shiro

Throughout 2014 I encountered a lot of cool, new (to me) programming tools. Bourbon, AngularJS, node.js, Homebrew and iTerm2 have all become welcome additions to my toolbox in that time. But there’s one tool among them which I’ve loved the most - Apache Shiro. Shiro is a Java security framework that manages to do the unthinkable: it makes Java security easy. I advocate for it every chance I get, and the responses I get are always positive.

Why is it special?

For a few reasons:

  • Shiro is application agnostic. It can lock down everything from a command line-based program to an Enterprise grade web application. It doesn’t care about how you use it or what you use it with. It just cares about offering security.
  • Shiro is based on a general purpose security model. If you’ve ever worked with Spring Security, or any of the Java EE security specifications, then you’ll be familiar with the key terms and concepts that define Shiro. The difference, however, is that many of those other frameworks redefine and otherwise butcher the meaning of many of these concepts. Shiro attempts to “take them back”, and give them the definitions they’re meant to have.
  • Shiro’s API takes these general security concepts turns them into Java interfaces. It also provides a few default implementations of these interfaces to help you get started. For some projects, the provided solutions may end up being all you need. However, as soon as you need something more, you can write a subclass and add your custom behavior (or simply create a fresh new class that implements one of the interfaces, in case you need some serious customization). In other words, Shiro provides some solutions to help you out, but it will also bend to your needs if need be. It always works for you, and not the other way around.
  • While it is app. agnostic, Shiro provides extra support libraries to help you use it in web applications and Spring-based applications. Its developers are generous enough to create something that everyone can use, but smart enough to know where it will be used the most.

Why do we need it?

Because most of the alternatives out there are not very good:

  • Most of the alternatives I’m about to mention are intended for use in web applications. Anything else is SOL, unless you can piece something together.
  • Shiro’s most obvious competitor is Spring Security, and I actually have nothing bad to say about it (though I like using Shiro more). However, I have been on projects which disallowed the use of any part of the Spring Framework. Oracle has done a very good job of waging a propaganda war against Spring (you can find one of the most famous examples here, and if you look at the results that come back from a Google search of Java EE vs Spring, you will see that their efforts have worked on a disturbing number of developers. TL:DR Spring Security is not always an option, in which case Shiro will be your best bet (unless that gets disallowed as well, which is a possibility if you’re dealing with a manager who has adopted a “Java EE only” stance).
  • About Java EE: more than anything else, I believe that its security solutions represent everything that is wrong with the entire Java EE concept. There are at least three different security solutions that are part of Java EE: JAAS, JAAC, and JASPIC. Oracle’s documentation does a terrible job at explaining this, or what the difference between any of them are. Absolutely none of them are container agnostic; at some point in time, any one of the three specs are going to force you to use JBoss/Glassfish/Websphere specific classes (why hello there vendor lock-in).

    This is miserable on its own, but it is made worse by the fact that JASPIC is supposed to be a container agnostic solution. The only problem is that the specification document is incomplete, and the JASPIC tests in the TCK are so crappy that they don’t even verify the features that are in the spec (if you want to know more about the state of security in Java EE, Arjan Tijms blog has more information than you knew existed. The man deserves a medal).

    In other words, Java EE’s security situation does the best job of demonstrating that just because something is a specification doesn’t mean that you’re free of vendor lock in, and just because you have a standard doesn’t mean it is thorough or well written. I can’t stand any of the three options, on a practical and moral level.

How do you use it?

This will largely depend on what kind of app you are writing, but here’s the basic setup for a Java web application:

  1. Define some Shiro Filters. These are Servlet filters that can perform various checks on incoming requests. For example, there’s a filter that will send users to a login page to authenticate, and one which will verify that incoming requests are encrypted. Writing a filter from scratch can by tricky, but I find there’s enough provided filters build off of.
  2. Define a Realm. In Shiro, a Realm is basically a security DAO. It can receive incoming credentials (which you’ll probably have saved in a Filter), and use them to retrieve the user’s information from your underlying security system (be it a database, an LDAP server, or whatever). It can then compare what you have stored against what the user presented, and see if they match.
  3. Shiro provides a flexible permissions system which allows you to add authorization features.
  4. Wire all the pieces together, either via Spring or config file or whatever.

What are the caveats?

Shiro can be a bit confusing at first. I found that it helps to read through the source code of some of the filters and realms. It will give you a better idea as to what actions are performed where, and in what order.

Secondly, while Shiro provides a lot of helpful implementation classes, they don’t cover a lot of advanced cases. You may very well find yourself writing some additional code. Thankfully, the framework encourages this, and it isn’t too hard to accommodate whatever it is you need.

Conclusion

All things considered, Shiro is pretty damn awesome. It is rigid when it needs to be, and flexibly otherwise. It helps me solve my security problems, without adding additional puzzles and mysteries as to how I should do it. I hope it continues to gain traction, and that more people will adopt it, even in the pure Java EE space.