Thursday, February 14, 2008

Acegi on Grails Tutorial

So, neither the information on the Plugin Page for the Acegi Security Plugin, nor the info in the acegi tutorial actually work completely. Here's a real tutorial for doing this. (Step 6 is where the existing documentation fails)

Step 1. Install Grails

Step 2. Download the Acegi Security Plugin. (I downloaded version 0.2 it as a zip file, to %GRAILS_HOME%/plugins/)

Step 3. Create a new Grails Project, and cd into the new project folder:

grails create-app SecurityTutorial
cd SecurityTutorial

Step 4. Add the Acegi Security Plugin. Note that you can install plugins by name using some lookup service, but the Acegi plugin won't be found.

grails install-plugin %GRAILS_HOME%/plugins/grails-acegi-0.2.zip

Step 5. Installing the Acegi Plugin will add some new scripts to your project:

  • create-auth-domains [PersonDomainName] [AuthorityDomainName: this creates the domain model needed by the plugin, Person, Authority, and RequestMap classes, login and logout controllers, as well as the login view. You can give optional names as arguments to replace Person and Authority.
  • generate-manager: creates the scaffolding controllers to add new Person, Authority, and RequestMap object in your database
  • generate-registration: create a register and captcha controller, as well as matching views, and an emailer service.

Run each of these commands.

grails create-auth-domains
grails generate-mapper
grails generate-registration

Step 6. Setup BootStrap.groovy to contain some sample data, as follows:

// ProjectFolder/grails-app/conf/Bootstrap.groovyclass BootStrap {

def init = { servletContext ->

// get a AcegiSecurity AuthenticateService
def authenticateService = new AuthenticateService()
// use it to create an encoded password
def md5pass = authenticateService.passwordEncoder("pass")

// Create two sample users
// NB: you must specify all the Person attributes, otherwise
// Grails will fail quietly to add these to the database
def user_root = new Person(username:"root",
userRealName:"Root User",
passwd:md5pass,
enabled:true,
email:"root@example.com",
email_show:true,
description:"Desc").save()
def user_admin = new Person(username:"admin",
userRealName:"Admin User",
passwd:md5pass,
enabled:true,
email:"admin@example.com",
email_show:false,
description:"Desc").save()

// Add some sample Roles, add the users to those roles
def role_superuser = new Authority(description:"Superuser",
authority:"ROLE_SUPERUSER")
role_superuser.addToPeople(user_root)
role_superuser.save()

// See AcegiConfig.groovy, at the bottom, there's a defaultrole
// setting, you must make one to allow registration to work.
def role_user = new Authority(description:"User Role",
authority:"ROLE_USER")
role_user.addToPeople(user_admin)
role_user.addToPeople(user_root)
role_user.save()

// Create some Request Maps
new Requestmap(url:"/captcha/**",
configAttribute:"ROLE_SUPERUSER").save()
new Requestmap(url:"/register/**",
configAttribute:"ROLE_USER").save()

}
def destroy = {
}
}

We also have to edit the RegisterController.groovy to fix a bug.

// ProjectFolder/grails-app/controllers/RegisterController.groovy                    // Line # 159-161
person.save(flush:true)
def parMap =['j_username':person.username,'j_password':params.passwd]
// change this line:
// redirect(controller:'login',action:'../j_acegi_security_check',params:parMap)
// to this:
redirect(controller:'login',action:"auth")

Step 7. Run the application

grails run-app

Step 8. Play around. Notice that you when you try to go to the register controller, it asks for a login, then, since you're already logged in, the register controller just shows you your info with a redirect(action "show"). Go delete the RequestMap for the register url, make sure you logout, then try again. See how the captcha is broken? Go remove the captcha RequestMap, and try again.

2 comments:

Anonymous said...

yes, i figure this as well.

However, the authenticationProcessingFilter is configured as /j_acegi_security_check in DefaultAcegiConfig . Will need to check why the spring filter is not working.

Unknown said...

very nice -- thanks for sharing!