Grails JSecurity Plugin version 0.4 released

I have finally released version 0.4 of the Grails JSecurity Plugin – see the release notes for more details.

This will be the last release under this name because JSecurity was renamed to Apache Shiro. All future work will now be done on the Shiro Plugin. You can already install a 1.0-SNAPSHOT version that is basically the JSecurity Plugin 0.4 rebadged.

Wildcard permissions

The most significant change in version 0.4 is native support for JSecurity’s WildcardPermission. “What’s that?” I hear you cry. A permission in JSecurity serves two purposes:

  1. it is a representation of a right or privilege that is required to access something, such as a document or a printer
  2. it represents one or more rights or privileges that a particular user has

So in order for a user to access a secured resource, his assigned rights must match (or “imply”) those required by the resource.

JSecurity implements permissions via an interface, called unsurprisingly Permission. You can create any type of permission you like, as long as it implements that interface. Objects get a bit clunky, though, when you start dealing with declarative access control. Consider this example access control filter:

import org.jsecurity.grails.JsecBasicPermission

class SecurityFilters {
    def filters = {
        main(controller: "*", action: "*") {
            before = {
                accessControl {
                    permission(new JsecBasicPermission(controllerName, actionName))
                }
            }
        }
    }
}

This example ensures that each controller action requires the user to have a permission specific to the controller name and action name. As I said, it’s clunky.

WildcardPermission is an implementation of the Permission interface that uses a single string to describe an arbitrary permission. The string must follow a certain pattern in order for the permission to work properly, but this is best demonstrated by example. Let’s take the previous example and modify it to use a wildcard permission:

class SecurityFilters {
    def filters = {
        main(controller: "*", action: "*") {
            before = {
                accessControl {
                    permission("$controllerName:$actionName")
                }
            }
        }
    }
}

We have managed to do away with the import and the permission requirement is now a simple string. The important thing to notice is that the controller and action names are separated by a colon, ‘:’. Each substring separated by a colon is called a part. As far as JSecurity and the WildcardPermission implementation are concerned, these parts have no inherent meaning. They don’t know that the first part is a controller name or that the second part is the name of an action. It’s up to the application to give the parts meaning and interpret them.

Of course, I’ve only shown you a permission requirement. How do you assign such a permission to a user? Well, assuming that you are using the default database realm that comes with the plugin, the code you need will look something like this:

class BootStrap {
    def init = { servletContext ->
        ...        
        // Wildcard permissions.
        def wildcardPermission = new JsecPermission(type: "org.jsecurity.authz.permission.WildcardPermission", possibleActions: "*").save()
        new JsecUserPermissionRel(user: user1, permission: wildcardPermission, target: "book:list,show", actions: "*").save()
        new JsecUserPermissionRel(user: user2, permission: wildcardPermission, target: "book:*", actions: "*").save()
        ...
    }
}

As you can see, you must first create an instance of the JsecPermission domain class for WildcardPermission. You can then link this permission to users via the JsecUserPermissionRel domain class. The target contains the permission string, while the actions property is ignored.

If you take a look at the first permission assignment, you’ll see that it allows the first user to access the list and show actions on the book controller. Notice how the assignment includes the names of two actions? These are sub-parts and they are separated by commas. It’s very unusual to see sub-parts in a permission requirement, but they are common in permission assignments like this. The second user has access to all the actions courtesy of the wildcard ‘*’.

In fact, you can have as many parts and sub-parts as you need. For example, we could add an extra part to the above permissions that represented a domain instance ID.

If you want to learn more about the rules that determine whether one permission string implies another, then take a look at the Javadoc for WildcardPermission. That’s all for now folks!

15 thoughts on “Grails JSecurity Plugin version 0.4 released

  1. John

    Hi Peter,

    First of all, thanks for maintaining the JSecurity/Shiro plugins. I really appreciate it. I’ve been deliberating between your plugins and ACEGI, and after reading for hours, I’ve finally decided to use JSecurity/Shiro.

    I am having a bit of an issue with the Shiro plugin, however. I just installed JSecurity and then realized that there were Shiro plugins also available, which brought me to your site. I uninstalled the JSecurity plugin (grails uninstall-plugin jsecurity) and then installed the Shiro plugin (grails install-plugin shiro) and received the following message:

    Base Directory: /Users/john/Development/pedestal
    Running script /Users/john/.grails/1.1.1/projects/pedestal/plugins/shiro-1.0-SNAPSHOT/scripts/QuickStart.groovy
    Error executing script QuickStart: No such property: jsecurityPluginDir for class: QuickStart
    groovy.lang.MissingPropertyException: No such property: jsecurityPluginDir for class: QuickStart
    at QuickStart.run(QuickStart:1)
    at QuickStart$run.call(Unknown Source)
    at gant.Gant.processTargets(Gant.groovy:494)
    at gant.Gant.processTargets(Gant.groovy:480)

    Any ideas?

  2. Peter Post author

    Hmmm…I don’t understand that. When I look at the code under the LATEST_RELEASE tag, it correctly refers to shiroPluginDir. Try uninstalling the plugin and then removing:

    ~/.grails/1.1.1/plugins/grails-shiro*
    You may have an old cached version of the plugin, which is a danger with SNAPSHOT releases unfortunately.

  3. John

    Hi Peter,

    Thanks for the quick response!

    Sorry for the confusion, I missed a step in my explanation. After installing the Shiro plugin, I ran the quick-start script (grails quick-start –prefix=””). That’s when the error message appeared. I hope that clears things up.

    I was also a bit confused when I took look at the QuickScript groovy file last night, as it was using shiroPluginDir, not jsecurityPluginDir. In any case, I’m at work right now, so I’ll give your suggestion a shot later tonight when I get home.

  4. Peter Post author

    Another possibility is that your script cache has the old JSecurity version in it. I suspect that’s more likely in fact. Try deleting ~/.grails/1.1.1/scriptCache/QuickStart*.

  5. John

    As you can tell, I’m fairly new to Grails. I was wondering if you could tell me if its safe to modify the domain class files installed by the QuickStart script. Would they be overwritten if I were to update the Shiro plugin?

  6. Peter Post author

    Your domain class files won’t be overwritten when you upgrade. If you run the “create-*-realm” or “quick-start” commands again, they will ask whether you want to overwrite the existing files.

  7. Peter Post author

    If you don’t modify your own copies, you can run them to get new versions if and when they are changed. But typically, if they work for you, then you might as well keep them as they are.

  8. John

    Hmmm, well in the least, I wouldn’t want to be in a position where modifying the domain classes prevents me from upgrading. I would like to be able to take advantage of any new features that may emerge.

    I’m thinking that I could always merge the new domain classes with my modified ones, but that will get a bit tedious if the upgrades are frequent and large. So I’m thinking subclassing the domain classes would be much easier.

    I only need to modify the JSecUser class, though. I just want to add a few extra attributes (i.e., email). I also want to keep the database representative of the actual domain classes being used in the system. So I’m thinking of making the JSecUser class an abstract data type, so no table is created for it. This would also render the JSecUser class un-instantiable. Is that going to cause any problems with Shiro?

  9. Peter Post author

    Making JSecUser abstract should work as long as you extend it with your own user domain class. I don’t think it’s particularly useful doing so, though, because the default Grails behaviour is for all domain classes in a hierarchy to share the same database table.

  10. Michael

    Peter, I’m not sure if you’ve seen the documentation page for Shiro on the grails plugin site. Go to:

    http://grails.org/plugin/shiro

    Imagine then that you are a new user trying for the first time to use Shiro. First of all you encounter the confusion with renaming, from jsecurity, to shiro, then to ki or whatever.

    Then you begin to follow the documentation, which you immediately get stuck with because it doesn’t say how to install the plugin.

    Maybe you’re smart enough to go and do a grails install-plugin shiro, but you’ll soon get stuck again because the quick-install doesn’t quite install all the files (no filter files are created) it should. As you then return to the documentation you find quite a cliff hanger at the bottom:

    “Of course, there are no users in the system yet, so you can’t successfully log in. Let’s rectify that now”

    THE END. That’s it. No more documentation.

    Peter, I an countless others appreciate the work that’s been done here, but what good is it if you’re the only one who understands how to use it?

    Please do two things before you even think of adding another feature or fixing a bug:

    First of all some decent documentation needs to be written. This is critical.

    Secondly it would be extremely nice if there was an out-of-the-box working example that one could download and just “grails run-app” right away.

    These two things would make it so much more easy for people like myself to appreciate the time and efford you and others have put into this project. Right now it’s causing nothing but frustration.

    Thanks for letting me blow off some steam here.

  11. Peter Post author

    Hi Michael,

    I’m afraid you caught the documentation in a transitional state as I prepare for a 1.0 release. As I was writing it, I realised that quick-start should probably do more than it does at the moment, hence the reference to a filters class. Certainly the JSecurity documentation is out of date, so that’s why I started to update the Shiro docs. As I get time, I’ll work some more on them.

    On the out-of-the-box example, you could always consider the grails.org application, although I believe that uses JSecurity still. Another option is Nimble, which is based on the Shiro plugin but provides extra features, including an admin UI. I’ll probably borrow its idea of creating a BootStrap class to create some test users for quick-start.

    Cheers,

    Peter

  12. Ashwini

    Hi Peter,

    I’m new to Grails and JSecurity. I could run basic application on grails and tried to use the JSecurity plugin. The import classes in any Realm file i create are showing up as unresolved errors. Is there a jar file I need to add somewhere to correct this?

    Thanks for your time,
    Ashwini

  13. Peter Post author

    Are you seeing these errors when you run the application via grails run-app at the command line? Or in your IDE? If the latter, make sure that the JSecurity JAR file is on the classpath.

    Also note that JSecurity has been renamed to Apache Shiro, so you should install the corresponding plugin: grails install-plugin shiro

Leave a Reply

Your email address will not be published. Required fields are marked *