Working with Rails

Recommend Brian on Working With Rails


Powered

JSecurity Permissions in Grails

Posted by Joseph Nusairat Wed, 04 Mar 2009 01:45:00 GMT

One of the security plugins I have looked at with the most interest is the JSecurity plugin. I was attracted to the JSecurity because it seemed to provide a good mix of out of the box support but also being flexible enough for customizations.

On the surface JSecurity provides much of the normal security you'd expect from any framework. There is out of the box support for login/logout authentication, support for role based lock downs, and finally even the ability to create permission based security. It's the last one I wanted to write about.

Understanding how to do normal authentication with JSecurity and implementing roles is pretty straight forward and the documentation on the grails wiki found here. Where I believe the documentation lacks a bit on is using permissions. That being said, the documentation on the wiki is very good at understanding WHAT permissions are and creating custom ones but not necessarily how to create basic ones in the first place.

I am going to assume you have all used JSecurity or can go to the previous URL and read about it and will discuss implementing permissions for JSecurity. Sometimes knowing when to use permissions can be rather complex. And sometimes justifiably so, the way to use permissions (and of course there are many ways to use them) is when you keep needing to fine tune access to a particular source on a per user basis. Take a typical web application with a user list. We may want to allow someone to have read access to the list, another to have read and write, and another to have read, write, delete. To perform this check with roles we would basically have to have 3 different roles and assign them when needed. The problem with this solution is it basically gets messy fast especially if you have quite a bit of resources you want to lock down in this way. Permissions are designed to solve this problem exactly, by allowing a finer grain access on a resource. Let's dive into how to create permissions in JSecurity.

How do we perform this in Grails with JSecurity? JSecurity essentially has three tables that handle permissioning: JsecPermission, JsecUSerPermissionRel, and JsecUserRoleRel. We will look at how these tables are going to help us create and lock down pages on a per user basis.

Let's first discuss how JSecurity interprets permisssions to begin with. JSecurity permission is more complex than some because it does not force one to treat every resource (ie: web page, file system, specific part of the app) equally. JSecurity allows you to define what the permission resource IS in the first place. For example the permission logic for a web URL like our in example of a user page, to-do page, etc would differ from a file resource if you were creating a documentation management site. The wiki for the JSecurity shows examples of a FilePermission or a ProjectPermission, anything that implements the Permission interface. Each of these classes will have an implies() methods that actually determines HOW one is to interpret the permission. This is great because it gives the user the maximum flexibilty in determining how they want there permission applied. Now while i say that is great, let's face it most of us are going to use permissions for as I described above in Grails, to lock down a particular controller / action. The good news is out of the box Grails JSecurity plugin provides a specialized permission for controller based security. They have what is called a basic permission 'org.jsecurity.grails.JsecBasicPermission'. This permission is good for when you want to apply the concept of controller / action security. And it is this particular use case I am going to show how to use below.

To start with even though we have the permission as a resource on the class path its name needs to be stored to the database so the system can do reflection on it later. The first table we need to add to is the JsecPermission table. This table is simply going to keep a list of all the permission classes we have and the possible actions for each. So for our controller / action lockdowns we will simply add a reference to the JsecBasicPermission into the database:

Creating the Database Permission

def perm = new JsecPermission(type: 'org.jsecurity.grails.JsecBasicPermission', possibleActions: '*').save() 

Now as you have noticed i have used an * for the possible actions, this is more to fill in the blanks than for anything useful. By default with the JsecBasePermission it really does not care about the actions used here. Now just because this particular permission is not using possible actions does not mean that another permission in the future could use it nor does it mean it HAS to use it either. This is part of JSecurity's methodology of trying to keep maximum flexibility.

Assigning the User to the Permissions Now that we created the permission let's assign it to a user you have already created. To assign it you basically have two choices. Either assign it to a role or assign the permission directly to the user. I am going to do the latter and assign it to the user. In the following code we are taking our user and our permission and allowing the actions of delete and edit.

new JsecUserPermissionRel(
    user : user,  
    permission: perm, 
    target : 'user', 
    actions : 'delete, edit').save() 

Locking Down the Resource

So now that we have the permission we are going to lock down the security for the controller, and here is where it may get a bit tricky to understand. First off remember we have not done any permissioning for create or list, so by default we do not want to do any permissioning check for those because we have not assigned any. So in our filter lets add two permissioning interceptors for delete and edit only:

user(controller: "register", action: "delete") {      
    before = { 
        accessControl { 
            permission(type: 'user', actions: actionName)
        }      
    } 
}  

user(controller: "register", action: "edit") {      
    before = {
        accessControl { 
            permission(type: 'user', actions: actionName) 
        }      
    } 
} 

Now the application will check for permissions with edit and delete only, and unless you are assigned will take you to a page saying that you aren't allowed.

Now where I said it can get confusing is the naming as you go through, and this is where we harp back to saying that the permissions in JSecurity is very much user based. While this provides a huge degree of flexibility it can also cause naming you thought should go together not always go together. So take where we initially defined type in the JsecPermission table. This type was our fully qualified class type. However, the type down in the filter we define has nothing to do with the JsecPermission type. This type is instead going to relate to the target we defined in JsecUserPermissionRel. This is an important distinction to make, and one that confused me at first when using the JsecBasicPermission. The actions part, that is more self explanatory and the actions you pass in will be the actions that it will check against.

Posted in ,  | Tags ,  | no comments | no trackbacks

Tags

agile drools gorm Grails Groovy Java orm Rails Ruby Security spring

Categories

Archives

Syndicate

Twitter