Wow! Please! Do it again!: Web Dev: Spring Security + JSF Ajax redirects

Wednesday, August 15, 2012

Web Dev: Spring Security + JSF Ajax redirects

I'm using SWF 2.3.1 (Spring Web Flow) + JSF (Mojarra 2.1.11) + PrimeFaces 3.4 RC1 Spring Security 3.1.2.

Scenario:
1. Upon login, user is presented with a form with a standard commandButton (which is ajax enabled by default)
2. Session timeout is set to 5 minutes in web.xml
3. After 10 minutes (user had to take a dump/leak), user comes back and clicks on the commandButton.

Outcome (actual):
Nothing happens, on screen at least. This is because Spring Security filters would trigger a server side redirect (HTTP Status Code 302), and the ajax client wasn't built to handle such response.

Outcome (expected):
User should be redirected to the login page, and optionally displaying some message like "Sorry, your session has timed out due to inactivity. Please login again."

Solution:
Create a custom JsfRedirectStrategy (extends org.springframework.security.web.DefaultRedirectStrategy). It will basically do the following:

1. Check if the current request is an Ajax one.
/**
 * Copied from org.springframework.faces.webflow.JsfAjaxHandler.isAjaxRequestInternal
 * @param request
 * @return
 */
private boolean isAjaxRequest(HttpServletRequest request) {
 String header = request.getHeader("Faces-Request");
 String param = request.getParameter("javax.faces.partial.ajax");
 return ("partial/ajax".equals(header) || "true".equals(param)) ? true : false;
}
2. If yes, output (spit out) XML, so that the ajax client will perform a server-side redirect.
3. If not, perform server-side redirect as usual (refer to DefaultRedirectStrategy).

Download source for JsfRedirectStrategy here.