Grails Cookbook - A collection of tutorials and examples

Grails Spring Security Core Plugin Example - Annotations

This example will show how to use Spring Security Core Plugin using annotations. This is one of the simplest way of using this plugin to secure your Grails applications.

Overview

The most popular security plugin for Grails is Spring Security Core. It is ideal to implement login and logout screens. As well as restricting access to specific screens with business rules.
Annotations can be used to restrict access to controllers. This is ideal if roles and access rules are fairly static and don't need to be changed at runtime.

Install Spring Security Core Plugin

The first step is to install the plugin by editing grails-app/conf/BuildConfig.groovy. Find the right plugin version for your Grails project version. Add entry similar to below in the plugins section:

grails.project.dependency.resolution = {
    ...
    plugins {
        ...
        compile ":spring-security-core:1.2.7.3"
    }
}

My Grails version in this sample is 2.2.4. And the most compatible plugin version is 1.2.7.3.

Try to run the application to download the plugin packages and integrate into the project:

grails run-app

Create Domain Classes


The plugin has a script to help create the domain classes. Issue this command on the console.
grails s2-quickstart asia.grails.sample SecUser SecRole

The parameters are as follows: package, user class, role class.
Three domain classes are created (Login and Logout controllers are also created). I removed some methods for conciseness.

SecUser - represents a user. Some properties are used for the state of the user (account enabled, account expired, etc). The password is also automatically hashed before saving to the database.

package asia.grails.sample
class SecUser {
	String username
	String password
	boolean enabled
	boolean accountExpired
	boolean accountLocked
	boolean passwordExpired
	def beforeInsert() {
		encodePassword()
	}
	def beforeUpdate() {
		if (isDirty('password')) {
			encodePassword()
		}
	}
	protected void encodePassword() {
		password = springSecurityService.encodePassword(password)
	}
}

SecRole - this represents a role given to a user.

package asia.grails.sample
class SecRole {
	String authority
	...
}

SecUserSecRole - this is the middle relationship table to relate user to a role (many to many relationship)

package asia.grails.sample
class SecUserSecRole implements Serializable {
	SecUser secUser
	SecRole secRole
	...
}

Create Test Data

Here is a sample data to play with security.
import asia.grails.sample.SecRole
import asia.grails.sample.SecUser
import asia.grails.sample.SecUserSecRole
class BootStrap {
    def init = { servletContext ->
        SecUser admin = new SecUser(username:'admin', password:'secret', enabled:true).save()
        SecUser john = new SecUser(username:'john', password:'secret', enabled:true).save()
        SecUser jane = new SecUser(username:'jane', password:'secret', enabled:true).save()
        SecRole royalty = new SecRole(authority: 'ROLE_ROYALTY').save()
        SecRole common = new SecRole(authority: 'ROLE_COMMON').save()
        SecUserSecRole.create(admin, royalty)
        SecUserSecRole.create(admin, common)
        SecUserSecRole.create(john, common)
    }
    def destroy = {
    }
}
Note that in Role class, the value of authority should start with "ROLE_". We have created 3 users:
  • admin - has common and royalty role
  • john - has common role only
  • jane - can login but has no roles

Securing Controller Actions By Annotations

This is how to annotate the actions in a controller to restrict access depending on roles:

package sample
import grails.plugins.springsecurity.Secured
class ScreenController {
    def publicPage() {
        render "This is a public page"
    }
    @Secured(['IS_AUTHENTICATED_FULLY'])
    def authenticatedPage() {
        render "This is a authenticated only page"
    }
    @Secured(['ROLE_COMMON'])
    def commonPage() {
        render "This is a common role page"
    }
    @Secured(['ROLE_ROYALTY'])
    def royalPage() {
        render "This is a royal role page"
    }
}

This is the behavior of each action:
  • publicPage - any user or visitor can access this page. Even for users that are not logged in.
  • authenticatedPage - only logged in user can view this page. Admin, john and jane can access this page.
  • commonPage - only user with ROLE_COMMON role can access this page. Both admin and john can access this page.
  • royalPage - only user with ROLE_ROYALTY role can access this page. Only admin can access this page.
When a user is not logged-in and an action with @Secured annotation is accessed, the user will be redirected to the login page.

When a user is logged in and an action is accessed without having the correct role, an error page is displayed:

Code

The full source code for this example can be viewed here or can be downloaded here.

Other Grails Plugins Tutorials


Tags: acegi, login, logout, Plugin, security, spring security