Monday, June 23, 2008

Tokens in Struts

Purpose: To prevent a page from being re-submitted when user hits refresh or hits submit multiple times or user clicks on back / forward on your browser and hits submit again

Solution: Tokens in Struts 2.0

Token Methods:

The methods we care about are:

saveToken(HttpServletRequest req)
isTokenValid(HttpServletRequest req)
resetToken(HttpServletRequest req)

Once of the basic concept for implementing tokens:

1) Always provide a setupForInsertOrUpdate dispatch method or indvidual Action. You could also break it up into setupForInsert and setupForUpdate if you so desire. Regardless, make sure you always go through this Action method before you go to your form.
2) In your setup method make sure to call "saveToken(request)." This puts a unique key into Session scope and will cause this token to be placed on your resulting JSP.
In your Action's update/insert dispatch method or your Action's execute method, make sure to first check if "isTokenValid(request)." This compares the token in Session with the one submitted through the Request. If they match, the token is valid and it's ok to procede with the update/insert. If they do not match, the user is likely simply resubmitting a stale page so we return from our action immediately. We need to remember before we leave our update/insert method that we call "resetToken(request)" so that we place a new token into Session scope, otherwise the old token will remain and it will match the one on the form and will allow duplicate submisssions.


Example:

public ActionForward setUpForInsertOrUpdate(ActionMapping mapping,
ActionForm form, HttpServletRequest request, HttpServletResponse response)
throws Exception {
logger.debug("setUpForInsertOrUpdate");
saveToken(request);
EmployeeForm employeeForm = (EmployeeForm)form;
if (isUpdate(request, employeeForm)) {
Integer id = Integer.valueOf(employeeForm.getEmployeeId());
Employee employee = empService.getEmployee(id);
BeanUtils.copyProperties(employeeForm, employee);
}
prep(request);
return mapping.findForward(Constants.SUCCESS);
}



public ActionForward insertOrUpdate(ActionMapping mapping,
ActionForm form, HttpServletRequest request, HttpServletResponse response)
throws Exception {
logger.debug("insertOrUpdate");
EmployeeForm employeeForm = (EmployeeForm)form;
if ( !isTokenValid(request) ) {
return mapping.findForward(Constants.INVALID_TOKEN);
}
if (validationSuccessful(request, employeeForm)) {
Employee employee = new Employee();
BeanUtils.copyProperties(employee, employeeForm);
if (isUpdate(request, employeeForm)) {
logger.debug("update");
empService.updateEmployee(employee);
} else {
logger.debug("insert" );
empService.insertEmployee(employee);
}
populateEmployees(request);
resetToken(request);
return mapping.findForward(Constants.SUCCESS);
} else {
prep(request);
return mapping.findForward(Constants.FAILURE);
}
}


-Smile ...tokens are making your life easy :D

No comments: