Skip to content

Instantly share code, notes, and snippets.

@banterCZ
Last active May 15, 2021 15:26
Show Gist options
  • Save banterCZ/5160269 to your computer and use it in GitHub Desktop.
Save banterCZ/5160269 to your computer and use it in GitHub Desktop.
InvalidSessionStrategy when session expired and ajax request is done.
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.security.web.session.InvalidSessionStrategy;
import org.springframework.util.StringUtils;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
/**
* Inspired by <a href="http://stackoverflow.com/questions/10143539/jsf-2-spring-security-3-x-and-richfaces-4-redirect-to-login-page-on-session-tim">StackOverflow.com</a>
* and by <a href="http://www.icesoft.org/wiki/display/ICE/Spring+Security#SpringSecurity-Step4%3AConfigureYourSpringSecurityredirectStrategy">Spring Security 3 and ICEfaces 3 Tutorial</a>.
*
* @author banterCZ
*/
public class JsfRedirectStrategy implements InvalidSessionStrategy {
private Logger logger = LoggerFactory.getLogger(getClass());
private static final String FACES_REQUEST_HEADER = "faces-request";
private String invalidSessionUrl;
/**
* {@inheritDoc}
*/
@Override
public void onInvalidSessionDetected(HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException {
boolean ajaxRedirect = "partial/ajax".equals(request.getHeader(FACES_REQUEST_HEADER));
if(ajaxRedirect) {
String contextPath = request.getContextPath();
String redirectUrl = contextPath + invalidSessionUrl;
logger.debug("Session expired due to ajax request, redirecting to '{}'", redirectUrl);
String ajaxRedirectXml = createAjaxRedirectXml(redirectUrl);
logger.debug("Ajax partial response to redirect: {}", ajaxRedirectXml);
response.setContentType("text/xml");
response.getWriter().write(ajaxRedirectXml);
} else {
String requestURI = getRequestUrl(request);
logger.debug("Session expired due to non-ajax request, starting a new session and redirect to requested url '{}'", requestURI);
request.getSession(true);
response.sendRedirect(requestURI);
}
}
private String getRequestUrl(HttpServletRequest request) {
StringBuffer requestURL = request.getRequestURL();
String queryString = request.getQueryString();
if (StringUtils.hasText(queryString)) {
requestURL.append("?").append(queryString);
}
return requestURL.toString();
}
private String createAjaxRedirectXml(String redirectUrl) {
return new StringBuilder()
.append("<?xml version=\"1.0\" encoding=\"UTF-8\"?>")
.append("<partial-response><redirect url=\"")
.append(redirectUrl)
.append("\"></redirect></partial-response>")
.toString();
}
public void setInvalidSessionUrl(String invalidSessionUrl) {
this.invalidSessionUrl = invalidSessionUrl;
}
}
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:sec="http://www.springframework.org/schema/security"
xsi:schemaLocation="http://www.springframework.org/schema/security http://www.springframework.org/schema/security/spring-security-3.1.xsd
http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.1.xsd">
<sec:http pattern="/pages/public/**" security="none"/>
<sec:http pattern="/javax.faces.resource/**" security="none"/>
<sec:http use-expressions="true" >
<sec:custom-filter ref="sessionManagementFilter" before="SESSION_MANAGEMENT_FILTER" />
<sec:intercept-url pattern="/pages/protected/**" access="isAuthenticated()" />
<sec:form-login login-page='/pages/public/login.xhtml' default-target-url="/pages/protected/index.xhtml"
authentication-failure-url="/pages/public/login.xhtml?failure=true" />
<sec:logout logout-success-url="/pages/public/login.xhtml"/>
</sec:http>
<sec:authentication-manager>
<sec:authentication-provider>
<sec:user-service>
<sec:user name="joe" password="password" authorities="ROLE_USER"/>
</sec:user-service>
</sec:authentication-provider>
</sec:authentication-manager>
<bean id="sessionManagementFilter" class="org.springframework.security.web.session.SessionManagementFilter">
<constructor-arg name="securityContextRepository" ref="httpSessionSecurityContextRepository" />
<property name="invalidSessionStrategy" ref="jsfRedirectStrategy" />
</bean>
<bean id="jsfRedirectStrategy" class="JsfRedirectStrategy">
<property name="invalidSessionUrl" value="/pages/public/error/viewExpired.xhtml" />
</bean>
<bean id="httpSessionSecurityContextRepository" class="org.springframework.security.web.context.HttpSessionSecurityContextRepository"/>
</beans>
<ui:composition template="/WEB-INF/templates/public_layout.xhtml"
xmlns="http://www.w3.org/1999/xhtml"
xmlns:h="http://java.sun.com/jsf/html"
xmlns:ui="http://java.sun.com/jsf/facelets"
>
<ui:param name="title" value="#{msg['error.viewExpired.title']}" />
<ui:define name="content">
#{msg['error.viewExpired.text']}
<h:outputLink value="#{header['referer']}">#{msg['link.back']}</h:outputLink>
</ui:define>
</ui:composition>
<?xml version="1.0" encoding="UTF-8"?>
<web-app version="3.0" xmlns="http://java.sun.com/xml/ns/javaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd">
<servlet>
<servlet-name>Faces Servlet</servlet-name>
<servlet-class>javax.faces.webapp.FacesServlet</servlet-class>
<load-on-startup>1</load-on-startup>
</servlet>
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>
classpath:security.xml
</param-value>
</context-param>
<listener>
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>
<listener>
<listener-class>org.springframework.security.web.session.HttpSessionEventPublisher</listener-class>
</listener>
<servlet-mapping>
<servlet-name>Faces Servlet</servlet-name>
<url-pattern>*.xhtml</url-pattern>
</servlet-mapping>
<filter>
<filter-name>springSecurityFilterChain</filter-name>
<filter-class>org.springframework.web.filter.DelegatingFilterProxy</filter-class>
</filter>
<filter-mapping>
<filter-name>springSecurityFilterChain</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
</web-app>
@rogerio-ar-costa
Copy link

Worked like a charm, thank you!

@agustisanchez
Copy link

Thanks!!!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment