My first groovy grails application – Sample Login with Spring Security


Why grails ?.

Good question right ?. See again question … please see the below points

  •  Provide a high-productivity web framework for the Java platform
  • Groovy code compiles to java bytecode 🙂
  •  Then it is running on JVM
  •  Open source using a BSD / Apache style licence. more interesting thing right
  • Groovy integrates with the Bean Scripting Framework, which allows you to embed any scripting engine into your Java code
  • Adding new methods to an object at runtime – i will show you this in my example

Required environmental setups

  1. Download and install jdk 1.6 or higher version
  2. Download groovy and set the environmental variables GRAILS_HOME and PATH http://dist.springframework.org.s3.amazonaws.com/release/GRAILS/grails-2.2.0.zip

STEP BY STEP

1. create new project
E:\tech\grailsapps> grails create-app grailsproject

message | Created Grails Application at E:\tech\grailsapps\grailsproject
See the initial structure of the application
initial structure

2 grails install-plugin spring-security-core

| Installed plugin spring-security-core-1.2.7.3

*******************************************************
* You’ve installed the Spring Security Core plugin.   *
* Next run the “s2-quickstart” script to initialize   *
* Spring Security and create your domain classes.     *
*******************************************************

| Plugin installed.

3 Create user, role, role-map classes for authentication
E:\tech\grailsapps\grailsproject>grails s2-quickstart com.orathel.gp.auth GUser GRole

*******************************************************
* Created domain classes, controllers, and GSPs. Your *
* grails-app/conf/Config.groovy has been updated with *
* the class names of the configured domain classes;   *
* please verify that the values are correct.          *
*******************************************************

What it do ?
It will create 3 domain classes and two controllers for login and logout, the required UI’s (gsp- groovy server pages). All the domain classes created in the domain folder
a.GUser.groovy

package com.orathel.gp.auth
/**
 * 

* GUser is the user class, with user name and password *

* @author praveen * */ class GUser { transient springSecurityService String username String password boolean enabled boolean accountExpired boolean accountLocked boolean passwordExpired static constraints = { username blank: false, unique: true password blank: false } static mapping = { password column: '`password`' } Set getAuthorities() { Set myrole = GUserGRole.findAllByGUser(this).collect { it.gRole } as Set Iterator iter = myrole.iterator(); Object first = iter.next(); System.out.println('this the size of hr role=>'+((GRole)first).authority) myrole } /** * Automatically the password will be encode * @return */ def beforeInsert() { encodePassword() } def beforeUpdate() { if (isDirty('password')) { encodePassword() } } protected void encodePassword() { password = springSecurityService.encodePassword(password) } }

b. GRole.groovy

 
package com.orathel.gp.auth
/**
 * 

* GRole : this class used to define the roles *

* @author praveen * */ class GRole { String authority static mapping = { cache true } static constraints = { authority blank: false, unique: true } }

c.GuserGRole.groovy

package com.orathel.gp.auth

import java.util.Set;
import org.apache.commons.lang.builder.HashCodeBuilder
/**
 * 

* This is the use role map class * one to many 1user ->m Role *

* @author praveen * */ class GUserGRole implements Serializable { /**User object*/ GUser gUser /**Role object*/ GRole gRole boolean equals(other) { if (!(other instanceof GUserGRole)) { return false } other.gUser?.id == gUser?.id && other.gRole?.id == gRole?.id } int hashCode() { def builder = new HashCodeBuilder() if (gUser) builder.append(gUser.id) if (gRole) builder.append(gRole.id) builder.toHashCode() } static GUserGRole get(long GUserId, long GRoleId) { find 'from GUserGRole where gUser.id=:GUserId and gRole.id=:GRoleId', [GUserId: GUserId, GRoleId: GRoleId] } static GUserGRole create(GUser gUser, GRole gRole, boolean flush = false) { new GUserGRole(gUser: gUser, gRole: gRole).save(flush: flush, insert: true) } static boolean remove(GUser gUser, GRole gRole, boolean flush = false) { GUserGRole instance = GUserGRole.findByGUserAndGRole(gUser, gRole) if (!instance) { return false } instance.delete(flush: flush) true } static void removeAll(GUser gUser) { executeUpdate 'DELETE FROM GUserGRole WHERE gUser=:gUser', [gUser: gUser] } static void removeAll(GRole gRole) { executeUpdate 'DELETE FROM GUserGRole WHERE gRole=:gRole', [gRole: gRole] } static mapping = { id composite: ['gRole', 'gUser'] version false } }

Now let us see the controllers
a. LoginController.groovy

import grails.converters.JSON

import javax.servlet.http.HttpServletResponse

import org.codehaus.groovy.grails.plugins.springsecurity.SpringSecurityUtils

import org.springframework.security.authentication.AccountExpiredException
import org.springframework.security.authentication.CredentialsExpiredException
import org.springframework.security.authentication.DisabledException
import org.springframework.security.authentication.LockedException
import org.springframework.security.core.context.SecurityContextHolder as SCH
import org.springframework.security.web.WebAttributes
import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter

class LoginController {

	/**
	 * Dependency injection for the authenticationTrustResolver.
	 */
	def authenticationTrustResolver

	/**
	 * Dependency injection for the springSecurityService.
	 */
	def springSecurityService

	/**
	 * Default action; redirects to 'defaultTargetUrl' if logged in, /login/auth otherwise.
	 */
	def index = {
		if (springSecurityService.isLoggedIn()) {
			redirect uri: SpringSecurityUtils.securityConfig.successHandler.defaultTargetUrl
		}
		else {
			redirect action: 'auth', params: params
		}
	}

	/**
	 * Show the login page.
	 */
	def auth = {
		def config = SpringSecurityUtils.securityConfig
		if (springSecurityService.isLoggedIn()) {
			redirect uri: config.successHandler.defaultTargetUrl
			return
		}
		String view = 'auth'
		String postUrl = "${request.contextPath}${config.apf.filterProcessesUrl}"
		render view: view, model: [postUrl: postUrl,
		                           rememberMeParameter: config.rememberMe.parameter]
	}

	/**
	 * The redirect action for Ajax requests.
	 */
	def authAjax = {
		response.setHeader 'Location', SpringSecurityUtils.securityConfig.auth.ajaxLoginFormUrl
		response.sendError HttpServletResponse.SC_UNAUTHORIZED
	}

	/**
	 * Show denied page.
	 */
	def denied = {
		if (springSecurityService.isLoggedIn() &&
				authenticationTrustResolver.isRememberMe(SCH.context?.authentication)) {
			// have cookie but the page is guarded with IS_AUTHENTICATED_FULLY
			redirect action: 'full', params: params
		}
	}

	/**
	 * Login page for users with a remember-me cookie but accessing a IS_AUTHENTICATED_FULLY page.
	 */
	def full = {
		def config = SpringSecurityUtils.securityConfig
		render view: 'auth', params: params,
			model: [hasCookie: authenticationTrustResolver.isRememberMe(SCH.context?.authentication),
			        postUrl: "${request.contextPath}${config.apf.filterProcessesUrl}"]
	}

	/**
	 * Callback after a failed login. Redirects to the auth page with a warning message.
	 */
	def authfail = {
		def username = session[UsernamePasswordAuthenticationFilter.SPRING_SECURITY_LAST_USERNAME_KEY]
		String msg = ''
		def exception = session[WebAttributes.AUTHENTICATION_EXCEPTION]
		if (exception) {
			if (exception instanceof AccountExpiredException) {
				msg = g.message(code: "springSecurity.errors.login.expired")
			}
			else if (exception instanceof CredentialsExpiredException) {
				msg = g.message(code: "springSecurity.errors.login.passwordExpired")
			}
			else if (exception instanceof DisabledException) {
				msg = g.message(code: "springSecurity.errors.login.disabled")
			}
			else if (exception instanceof LockedException) {
				msg = g.message(code: "springSecurity.errors.login.locked")
			}
			else {
				msg = g.message(code: "springSecurity.errors.login.fail")
			}
		}

		if (springSecurityService.isAjax(request)) {
			render([error: msg] as JSON)
		}
		else {
			flash.message = msg
			redirect action: 'auth', params: params
		}
	}

	/**
	 * The Ajax success redirect url.
	 */
	def ajaxSuccess = {
		render([success: true, username: springSecurityService.authentication.name] as JSON)
	}

	/**
	 * The Ajax denied redirect url.
	 */
	def ajaxDenied = {
		render([error: 'access denied'] as JSON)
	}
}

b. LogoutController.groovy

import org.codehaus.groovy.grails.plugins.springsecurity.SpringSecurityUtils

class LogoutController {

	/**
	 * Index action. Redirects to the Spring security logout uri.
	 */
	def index = {
		// TODO put any pre-logout code here
		redirect uri: SpringSecurityUtils.securityConfig.logout.filterProcessesUrl // '/j_spring_security_logout'
	}
}

It will also create the following configurations in your Config.groovy
Result———– Config.groovy // Added by the Spring Security Core plugin: grails.plugins.springsecurity.userLookup.userDomainClassName = ‘com.orathel.gp.auth.GUser’ grails.plugins.springsecurity.userLookup.authorityJoinClassName = ‘com.orathel.gp.auth.GUserGRole’ grails.plugins.springsecurity.authority.className = ‘com.orathel.gp.auth.GRole’

Actually what is this ?
These configuration will tell the framework that what are all the classes we defined for authentication and authorization.
We just defined the classes right, now let us define the fields I mean the username field, password, rolename etc.
DefaultSecurityConfig.groovy
// user and role class properties
userLookup.userDomainClassName = ‘Guser’
userLookup.usernamePropertyName = ‘username’
userLookup.enabledPropertyName = ‘enabled’
userLookup.passwordPropertyName = ‘password’
userLookup.authoritiesPropertyName = ‘authorities’
userLookup.accountExpiredPropertyName = ‘accountExpired’
userLookup.accountLockedPropertyName = ‘accountLocked’
userLookup.passwordExpiredPropertyName = ‘passwordExpired’
userLookup.authorityJoinClassName = ‘GuserGRole’
authority.className = ‘GRole’
authority.nameField = ‘authority’

I i know what you are thinking now. where is the database cobfugurations right
Please check the DataSorce.groovy in the conf folder, the default is hsql db for runtime initialization you can configure your own.

4 Execute the application

Before executing, for testing we need to have a test user right, so I am creating one test user and test role for authorization
Here we have class named BootStrap.groovy, this classes init portion will execute while application startup. So I modified the class

import com.orathel.gp.auth.*
/**
 * 
 * 

This class will invoke during startup * The init portion will create basic setting :- * 1. Creates the default users * 2. Creates the default roles * 3. First user role mapping *

* * @author praveen * */ class BootStrap { transient springSecurityService def init = { servletContext -> if(!GUser.count()){ /*The default password is 'password'*/ def password = 'password' def user = new GUser(username : 'praveen', password:password,enabled:true, accountExpired : false , accountLocked : false ,passwordExpired : false).save(flush: true, insert: true) def role = new GRole(authority : 'ROLE_USER').save(flush: true, insert: true) /*create the first user role map*/ GUserGRole.create user , role , true } } def destroy = { } }

See I told you know I will show you about run time method adding, see this class we dont have save method in GUSer / GRile but still i called because save method will add to these classes at runtime, read more ..

Ok now its ready for running
Command :– E:\tech\grailsapps\grailsproject>grails run-app
| Server running. Browse to http://localhost:8080/grailsproject

Again doubt where is the server ?. tomact 7 is integrated with groovy and your application started on tomcat 7 !!!!!1

Advertisements

About Praveen Orathel

I am a java web application developer.
This entry was posted in Uncategorized and tagged , , , , . Bookmark the permalink.

One Response to My first groovy grails application – Sample Login with Spring Security

  1. I just wanted to let you know that I tried this with Grails 2.2.2 and found a problem. I believe this is because of the domain names GUser and GRole having uppercase in the second position. I tried the above using SecurityUser and Role (as detailed in some other Grails source I had) and it worked fine.

    The error(s) I received with

    Error 500: Internal Server Error

    URI
    /grailsproject/j_spring_security_check
    Class
    org.codehaus.groovy.grails.exceptions.InvalidPropertyException
    Message
    No property found for name [gUser] for class [class com.dbirtwell.auth.GUserGRole]

    Around line 24 of grails-app\domain\com\dbirtwell\auth\GUser.groovy

    21: }
    22:
    23: Set getAuthorities() {
    24: GUserGRole.findAllByGUser(this).collect { it.GRole } as Set
    25: }
    26:
    27: def beforeInsert() {

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s