Grails Cookbook - A collection of tutorials and examples

Grails Spring Security Core Plugin Example - Static URL Map Rules

This example will show how to use Spring Security Core Plugin using static URL map rules. Similar to annotations, this is also a simple 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.
Static URL Map can be used to restrict access to controllers. The restriction configuration is written in Config.groovy. This is an alternative if you are not a fan of annotations and roles / access rules are fairly static.

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

This is a sample controller with some actions:

package sample
class ScreenController {
    def publicPage() {
        render "This is a public page"
    }
    def authenticatedPage() {
        render "This is a authenticated only page"
    }
    def commonPage() {
        render "This is a common role page"
    }
    def royalPage() {
        render "This is a royal role page"
    }
}

At this stage, you can access all the pages regardless of user used to login. Even users not logged in can access the pages. To do the restriction via static URL map, edit grails-app/conf/Config.groovy and add the following lines:

import grails.plugins.springsecurity.SecurityConfigType

grails.plugins.springsecurity.securityConfigType = SecurityConfigType.InterceptUrlMap grails.plugins.springsecurity.interceptUrlMap = [ '/screen/authenticatedPage': ['IS_AUTHENTICATED_FULLY'], '/screen/commonPage': ['ROLE_COMMON'], '/screen/royalPage': ['ROLE_ROYALTY'], '/**': ['IS_AUTHENTICATED_ANONYMOUSLY'] ]

This is the behavior of each action after using the configuration above:
  • 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.
Note that the '/**' section is a catch all. And the role required is anonymous, meaning any user or visitor can access. Even for users that are not logged in. This will be the behavior of publicPage action as it is not a match with the other rules.
When a user is not logged-in and a restricted page 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