logo

Gravl: Implementing Security on the Cheap…

logo

Grails Filters open up a whole new world of opportunity for jumping into the request pipeline to do your own custom processing. I’m really excited about getting Referer tracking real soon now, since I’ve learned the basics of Filters when I implemented Gravl’s very basic security model.

The Grails community is working on some first class plugins for Acegi and JSecurity, but for if your security model is coarse grain (authenticated users can do this, everyone else can’t), it’s easy enough to write a simple custom filter for the task (and a good way to learn filters to boot!).

First we’ll add a SecurityFilters class to the conf directory. Then we’ll get busy declaring our filter logic…

def filters = {

        loginCheck(controller: '*', action: '*') {

            before = {
                      // do our security checks here, before the controller action is invoked...
            }
      }
}

Based on some ideas I picked up from The Bishop (The Grails CMS sample includes users with certain roles can do certain things, but that was overkill for Gravl), I hold the security model in an a hashmap, where I map the controller name to a list of public actions.

def publicStuff = [
    "blog" : ["archive", "homePage", "displayOneEntry"],
    "comment" : ["newComment", "preview", "save"],
    "feed": ["feeds"],
    "pdf": ["show"],
    "image" : ["display"],
    "login" : ["form", "login"]
]

Then it’s a matter of checking whether (1) you have an account object in your session – in which case you’re in, or (2) If you aren’t authenticated, make sure the action you’re invoking is in the public list. If you’re heading for a secured page as an unauthenticated user, I send you off to login. Filters don’t seem to have a logger injected at the moment, so excuse my printlns, but I’m sure they’ll be there soon:

if (!session.account) {
	boolean allowed = false

	println "Checking access to controller [${controllerName}] with action [${actionName}] (${request.forwardURI})"

	if (publicStuff.keySet().find { it == controllerName }) {

		if (publicStuff[controllerName].find { it == actionName }) {
			println "Access ok to public controller [${controllerName}] with action [${actionName}]"
			if (controllerName != 'login') // keep last unsecured page in session for post-login return
				session.returnurl = request.forwardURI
			allowed = true
		} else {
			println "Access privileged action: ${actionName}"
			allowed = false
		}

	} else {
		allowed = false
		println "Access privileged controller: ${controllerName}"

	}

	if (!allowed) {
		session.returnurl = request.forwardURI
		println "Setting return url to " + session.returnurl
		redirect(controller: 'login', action: 'form')
	}

	return allowed
} else {
	println "Found user in session"
	return true
}

And you’re up and running with a basic security model! Still need to implement a basic “remember me” cookie, but the sirens of referer tracking are singing… I can feel a RefererFilters class coming on…

In the meantime, have fun with the lightweight security goodness that filters open up… Can’t wait to see the next generation of plugins that use this stuff!

3 Responses to “Gravl: Implementing Security on the Cheap…”

  1. Sakuraba says:

    With Acegi, you would have had exactly the same behaviour + your RememberMe feature all in a declarative manner based on a proven and robust security framework.

    But maybe the xml would have not been groovy-like and would have wasted too much of the 1000 lines limit ;)

  2. Dierk König says:

    cool (as always ;-) )
    minor point: you can write
    publicStuff.keySet().find { it == controllerName })
    as
    publicStuff.keySet().contains controllerName
    which reads slightly better.

    Can’t wait to see the full Gravl code!

  3. @Dierk

    Couldn’t you just write

    if(publicStuff[controllerName]) {
    /// etc.
    }

    Or am I missing something

Leave a Reply

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

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>

logo
logo
Powered by WordPress | Designed by Elegant Themes