Archive | March, 2013

useToken Grails 2.1.1

8 Mar

When upgrading my project from grails 1.3.5 to 2.1.1, I face several problems, one of it is useToken as an attribute of grails form.

So in my page, I have several g:form with useToken in all of it as bellow:

<g:form name="form1" action="save1" useToken="true">
	<input type="submit" value="Save"/>
</g:form>
<g:form name="form2" action="save2" useToken="true">
	<input type="submit" value="Save"/>
</g:form>

and my controller was like this:

def save1 = {
	withForm {
	}.invalidToken {
		redirect(controller: "error", action: "forbidden")
	}
}
def save2 = {
	withForm {
	}.invalidToken {
		redirect(controller: "error", action: "forbidden")
	}
}

as the result I always go to the forbidden page when submitting the form.

After several inspection on the element, I discovered that the hidden field value generated by the useToken attribute is different (in form1 and form2) while in grails 1.3.5 it is the same.

In FormTagLib.groovy (provided by grails core), bellow is part of the code used to generate the hidden field of the token:

def tokensHolder = SynchronizerTokensHolder.store(session)
writer.println()
hiddenFieldImpl(writer, [name: SynchronizerTokensHolder.TOKEN_KEY, value: tokensHolder.generateToken(request.forwardURI)])
writer.println()
hiddenFieldImpl(writer, [name: SynchronizerTokensHolder.TOKEN_URI, value: request.forwardURI])

So I change my page to become like this:

<%
	def tokensHolder = org.codehaus.groovy.grails.web.servlet.mvc.SynchronizerTokensHolder.store(session)
	def tokennya = tokensHolder.generateToken(request.forwardURI)
	def tokenurlnya = request.forwardURI
%>
<g:form name="form1" action="save1">
	<g:hiddenField name="${org.codehaus.groovy.grails.web.servlet.mvc.SynchronizerTokensHolder.TOKEN_KEY}" value="${tokennya}"/>
	<g:hiddenField name="${org.codehaus.groovy.grails.web.servlet.mvc.SynchronizerTokensHolder.TOKEN_URI}" value="${tokenurlnya}"/>
	<input type="submit" value="Save"/>
</g:form>
<g:form name="form2" action="save2">
	<g:hiddenField name="${org.codehaus.groovy.grails.web.servlet.mvc.SynchronizerTokensHolder.TOKEN_KEY}" value="${tokennya}"/>
	<g:hiddenField name="${org.codehaus.groovy.grails.web.servlet.mvc.SynchronizerTokensHolder.TOKEN_URI}" value="${tokenurlnya}"/>
	<input type="submit" value="Save"/>
</g:form>

and my problem solved 😀