Last updated by 5 years ago

Page: Simple Dynamic Password Codec, Version:2

Grails grants you the ability to quickly define dynamic codecs that you can easily call from within your Grails app. One of the most common uses of a such codecs in web applications is the creation of one-way hashed password strings. Grails makes this very easy to implement and use.

First, create a new codec in /grails-app/utils.

/grails-app/utils/PasswordCodec.groovy:

import java.security.MessageDigest
import sun.misc.BASE64Encoder
import sun.misc.CharacterEncoder

class PasswordCodec {

static encode = { str -> MessageDigest md = MessageDigest.getInstance('SHA') md.update(str.getBytes('UTF-8')) return (new BASE64Encoder()).encode(md.digest()) }

}

You only need to define the encode closure (codecs may also have a decode closure, but you don't need one for a one-way hash). The above encode closure accepts a string parameter (str). It then creates a SHA-1 MessageDigest to digest the string. The digested string (an array of bytes) is handed off to a Base64Encoder to turn it into the returned encoded hashed string.

You may now call this codec on any string in your grails appplication by calling {{someString.encodeAsPassword()}}. Here is a complete user controller (modified from the one in _Grails - The Definitive Guide_, pgs. 159-167) that uses the PasswordCodec to encode the password when the user registers and to compare an entered password with a stored password when the user logs in.

/grails-app/controllers/UserController.groovy:

class UserController {

def login = { if (session.user) { redirect(controller:'topic', action:'list') } }

def handleLogin = { def user = User.findByEmail(params.email) if (user) { if (user.password == params.password.encodeAsPassword()) { session.user = user redirect(controller:'topic', action:'list') } else { flash.message = "Incorrect password for ${params.email}" redirect(action:login) } } else { flash.message = "User not found for email ${params.email}" redirect(action:login) } }

def register = {}

def handleRegistration = { def user = new User(params) if (params.password != params.confirm) { flash.message = "The passwords you entered do not match." redirect(action:register) } else { user.password = params.password.encodeAsPassword() if (user.save()) { redirect(controller:'topic', action:'list') } else { flash.user = user redirect(action:register) } } } }