How to handle expired session using Spring Security and jQuery? How to handle expired session using Spring Security and jQuery? ajax ajax

How to handle expired session using Spring Security and jQuery?


Here's an approach that I think is quite simple. It's a combination of approaches that I've observed on this site. I wrote a blog post about it:http://yoyar.com/blog/2012/06/dealing-with-the-spring-security-ajax-session-timeout-problem/

The basic idea is to use an api url prefix (i.e. /api/secured) as suggested above along with an authentication entry point. It's simple and works.

Here's the authentication entry point:

package com.yoyar.yaya.config;import org.springframework.security.core.AuthenticationException;import org.springframework.security.web.authentication.LoginUrlAuthenticationEntryPoint;import javax.servlet.ServletException;import javax.servlet.http.*;import java.io.IOException;public class AjaxAwareAuthenticationEntryPoint              extends LoginUrlAuthenticationEntryPoint {    public AjaxAwareAuthenticationEntryPoint(String loginUrl) {        super(loginUrl);    }    @Override    public void commence(        HttpServletRequest request,         HttpServletResponse response,         AuthenticationException authException)             throws IOException, ServletException {        boolean isAjax             = request.getRequestURI().startsWith("/api/secured");        if (isAjax) {            response.sendError(403, "Forbidden");        } else {            super.commence(request, response, authException);        }    }}

And here's what goes in your spring context xml:

<bean id="authenticationEntryPoint"  class="com.yoyar.yaya.config.AjaxAwareAuthenticationEntryPoint">    <constructor-arg name="loginUrl" value="/login"/></bean><security:http auto-config="true"  use-expressions="true"  entry-point-ref="authenticationEntryPoint">    <security:intercept-url pattern="/api/secured/**" access="hasRole('ROLE_USER')"/>    <security:intercept-url pattern="/login" access="permitAll"/>    <security:intercept-url pattern="/logout" access="permitAll"/>    <security:intercept-url pattern="/denied" access="hasRole('ROLE_USER')"/>    <security:intercept-url pattern="/" access="permitAll"/>    <security:form-login login-page="/login"                         authentication-failure-url="/loginfailed"                         default-target-url="/login/success"/>    <security:access-denied-handler error-page="/denied"/>    <security:logout invalidate-session="true"                     logout-success-url="/logout/success"                     logout-url="/logout"/></security:http>


I used the following solution.

In spring security defined invalid session url

<security:session-management invalid-session-url="/invalidate.do"/>

For that page added following controller

@Controllerpublic class InvalidateSession{    /**     * This url gets invoked when spring security invalidates session (ie timeout).     * Specific content indicates ui layer that session has been invalidated and page should be redirected to logout.      */    @RequestMapping(value = "invalidate.do", method = RequestMethod.GET)    @ResponseBody    public String invalidateSession() {        return "invalidSession";    }}

And for ajax used ajaxSetup to handle all ajax requests:

// Checks, if data indicates that session has been invalidated.// If session is invalidated, page is redirected to logout   $.ajaxSetup({    complete: function(xhr, status) {                if (xhr.responseText == 'invalidSession') {                    if ($("#colorbox").count > 0) {                        $("#colorbox").destroy();                    }                    window.location = "logout";                }            }        });


Take a look at http://forum.springsource.org/showthread.php?t=95881, I think the proposed solution is much clearer than other answers here:

  1. Add a custom header in your jquery ajax calls (using 'beforeSend' hook). You can also use the "X-Requested-With" header that jQuery sends.
  2. Configure Spring Security to look for that header in the server side to return a HTTP 401 error code instead of taking the user to the login page.