Suresh Payankannur

Tuesday, September 23, 2014

Spring Security and Ajax Session Expiry

One of the requirement in a recent project was to capture the Ajax session expiry and send a JSON response back to the client if the session was expired. There are a few different ways to handle this in Spring Security. Here is one approach

<bean id="ajaxRequestMatcher" class="com.mycompany.AjaxRequestMatcher"/>

  <bean id="loginEntryPoint"
        class="org.springframework.security.web.authentication.LoginUrlAuthenticationEntryPoint">
    <constructor-arg value="/login.jsp" />
  </bean>

  <bean id="ajaxEntryPoint"
        class="com.mycompany.AjaxAuthenticationEntryPoint" />
  
  <bean id="authenticationRequestCache"
        class="org.springframework.security.web.savedrequest.HttpSessionRequestCache">
    <property name="requestMatcher" ref="ajaxRequestMatcher" />
  </bean>

  <bean id="authenticationEntryPoint"
        class="org.springframework.security.web.authentication.DelegatingAuthenticationEntryPoint">
    <constructor-arg>
      <map>
        <entry key-ref="ajaxRequestMatcher" value-ref="ajaxEntryPoint" />
      </map>
    </constructor-arg>
    <property name="defaultEntryPoint" ref="loginEntryPoint" />
  </bean>

  <security:http entry-point-ref="authenticationEntryPoint">
    <security:intercept-url
        access="IS_AUTHENTICATED_REMEMBERED"
        pattern="/secure/**"/>

    <security:form-login
        login-page="/login.jsp"/>
    <security:logout/>

  </security:http>

Java Classes

public class AjaxRequestMatcher implements RequestMatcher {
    public boolean matches(HttpServletRequest request) {
        return "XMLHttpRequest".equals(request.getHeader("X-Requested-With"));
    }
}

public class AjaxAuthenticationEntryPoint extends LoginUrlAuthenticationEntryPoint {
    @Override
    public void commence(HttpServletRequest request,
                         HttpServletResponse response,
                         AuthenticationException authException)
        throws IOException, ServletException {    

        // form json string
        String json = ....

        response.setContentType(MediaType.APPLICATION_JSON_VALUE);
        response.setHeader("Cache-control", "no-cache");
        response.setStatus(HttpServletResponse.SC_FORBIDDEN);

        response.getWriter().print(json);
        response.getWriter().flush();
        response.getWriter().close();
    }
}



2 comments:

  1. An interesting reading :)
    You could use @ResponseBody and @ResponseStatus + return Map instead of writing directly to response. Additionally your solution contains a small flaw - JSON response in places where JSTL views are returned may be a bit tricky to handle in the frontend layer.

    ReplyDelete
    Replies
    1. Thanks for your input.

      But I am not using Spring MVC at all. The implementation uses Spring Security with JAX-RS (RestEasy).

      Delete

Blog Archive

Scroll To Top