Hi,

I'm developing richfaces application with webflow 2.0.7, richfaces 3.3.1 and spring security 2.0.5.

I have a form with selectOneMenu that makes an ajax request on change and rerenders another selectOneMenu.

The problem is that if I make the ajax requiest after the session timeout, I'm redirected to the login page, but after that I recieve strange XML :
Code:
<?xml version="1.0" encoding="UTF-8"?>
<html xmlns="http://www.w3.org/1999/xhtml"><head><meta name="Ajax-Response" content="redirect" /><meta name="Location" content="/Schoolix/groups/new.sp" /></head></html>
After some investigation I found the problem and the solution.

The problem is in the BaseXMLFilter in richfaces and specially in this code

Code:
if (null != redirectLocation) {
			if (isAjaxRequest(request)) {
				// Special handling of redirect - client-side script must
				// Check for response and perform redirect by window.location
				if (log.isDebugEnabled()) {
					log.debug("Create AJAX redirect response to url: "
							+ redirectLocation);
				}
				output = resetResponse(response, servletResponseWrapper,
						"redirect");
				response.setHeader(AjaxContainerRenderer.AJAX_LOCATION_HEADER,
						redirectLocation);
				// For buggy XmlHttpRequest realisations repeat headers in
				// <meta>
				output.write("<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n"
						+ "<html xmlns=\"http://www.w3.org/1999/xhtml\"><head>"
						+ "<meta name=\""
						+ AjaxContainerRenderer.AJAX_FLAG_HEADER
						+ "\" content=\"redirect\" />" + "<meta name=\""
						+ AjaxContainerRenderer.AJAX_LOCATION_HEADER
						+ "\" content=\"" + redirectLocation + "\" />"
						+ "</head></html>");
				output.flush();
				response.flushBuffer();
			} else {
				response.sendRedirect(redirectLocation);
			}
As it is written in the comment "Special handling of redirect - client-side script must // Check for response and perform redirect by window.location" we need to redirect manually, but since our XMLHTTPRequest callback is no longer available we cannot do anything from the client.

So we need normal redirect, not the ajax one. This is determined with the following function in BaseXMLFilter
Code:
	protected boolean isAjaxRequest(ServletRequest request) {
		try {
			return null != request
					.getParameter(AjaxContainerRenderer.AJAX_PARAMETER_NAME);
		} catch (Exception e) {
			// OCJ 10 - throw exception for static resources.
			return false;
		}
	}
I traced the request and this is the request stored by the ExceptionTranslationFilter#sendStartAuthentication :
Code:
	protected void sendStartAuthentication(ServletRequest request, ServletResponse response, FilterChain chain,
			AuthenticationException reason) throws ServletException, IOException {
		HttpServletRequest httpRequest = (HttpServletRequest) request;

		SavedRequest savedRequest = new SavedRequest(httpRequest, portResolver);

		if (logger.isDebugEnabled()) {
			logger.debug("Authentication entry point being called; SavedRequest added to Session: " + savedRequest);
		}

		if (createSessionAllowed) {
			// Store the HTTP request itself. Used by AbstractProcessingFilter
			// for redirection after successful authentication (SEC-29)
			httpRequest.getSession().setAttribute(AbstractProcessingFilter.SPRING_SECURITY_SAVED_REQUEST_KEY, savedRequest);
		}

		// SEC-112: Clear the SecurityContextHolder's Authentication, as the
		// existing Authentication is no longer considered valid
		SecurityContextHolder.getContext().setAuthentication(null);

		authenticationEntryPoint.commence(httpRequest, response, reason);
	}
So my solution is to remove the parameter from the request if the session is timed out:

Code:
package eu.dreamix.schoolix.view.security;

import java.io.IOException;

import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServletRequest;

import org.ajax4jsf.renderkit.AjaxContainerRenderer;
import org.springframework.security.AuthenticationException;
import org.springframework.security.ui.AbstractProcessingFilter;
import org.springframework.security.ui.savedrequest.SavedRequest;
import org.springframework.security.ui.webapp.AuthenticationProcessingFilterEntryPoint;
import org.springframework.security.util.PortResolverImpl;

/**
 * @author Cvetelin Andreev Date: 26.08.2009
 */
public class FixAjaxRedirectEntryPoint extends
		AuthenticationProcessingFilterEntryPoint {
	@SuppressWarnings("serial")
	@Override
	public void commence(ServletRequest request, ServletResponse response,
			AuthenticationException authException) throws IOException,
			ServletException {
		super.commence(request, response, authException);

		if (request instanceof HttpServletRequest) {

			if (true == isAjaxRequest(request)) {
				HttpServletRequest httpRequest = (HttpServletRequest) request;

				SavedRequest savedRequest = new SavedRequest(httpRequest,
						new PortResolverImpl()) {
					@Override
					public String[] getParameterValues(String name) {
						if (AjaxContainerRenderer.AJAX_PARAMETER_NAME == name) {
							return null;
						}
						return super.getParameterValues(name);
					}
				};
				httpRequest.getSession().setAttribute(
								AbstractProcessingFilter.SPRING_SECURITY_SAVED_REQUEST_KEY,
								savedRequest);
			}

		}
	}

	protected boolean isAjaxRequest(ServletRequest request) {
		try {
			return null != request
					.getParameter(AjaxContainerRenderer.AJAX_PARAMETER_NAME);
		} catch (Exception e) {
			return false;
		}
	}

}
and the custom entry point configuration
Code:
<?xml version="1.0" encoding="UTF-8"?>

<beans:beans xmlns="http://www.springframework.org/schema/security"
	xmlns:beans="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xsi:schemaLocation="
		http://www.springframework.org/schema/beans 
		http://www.springframework.org/schema/beans/spring-beans-2.5.xsd
        http://www.springframework.org/schema/security
        http://www.springframework.org/schema/security/spring-security-2.0.4.xsd">

	<http auto-config='true' access-denied-page="/login.sp"
		entry-point-ref="fixAjaxRedirectEntryPoint">
		<intercept-url pattern="/css/**" filters="none" />
		<intercept-url pattern="/a4j/**" filters="none" />
		<intercept-url pattern="/login.sp**" filters="none" />

		<intercept-url pattern="/**" access="ROLE_USER" />

		<form-login login-page="/login.sp"
			authentication-failure-url="/login.sp?login_error=1" />
		<logout logout-success-url="/login.sp" />
	</http>

	<authentication-provider>
		<user-service>
			<user name="cvetelin.andreev@dreamix.eu" password=""
				authorities="ROLE_USER" />
			<user name="mimi.maneva@gmail.com" password="dupe" authorities="ROLE_USER" />
		</user-service>
	</authentication-provider>

	<beans:bean id="fixAjaxRedirectEntryPoint"
		class="eu.dreamix.schoolix.view.security.FixAjaxRedirectEntryPoint">
		<beans:property name="loginFormUrl" value="/login.sp"></beans:property>
	</beans:bean>

</beans:beans>