0
votes

In Spring Security, how to exclude one particular URL from resetting the session timeout? Overall application session timeout(server.servlet.session.timeout) is 15 minutes. We have a ajax call from the web page that will get called every 1 minute. This call needs to be secured, but should not impact the session time.

We have tried adding a filter extending ConcurrentSessionFilter. Also, a filter extending SessionManagementFilter. Adding ignoring() skips authentication too. Nothing helped. Can this requirement be achieved in Spring Security? Any suggestions?

1
If you don't want to extend the session, don't send the session cookie.However, that means that you can't use the existing session and also you are not logged in. Do you need the session for more than authentication in your AJAX call? - dur
Thank you @dur . Yes, we need session only for authentication for this URL. - Niyas
Then you could use no session for this URL and auhenticate with HTTP basic. - dur
Thank you @dur . We need the user to authenticate himself via login. Once he logs-in ,we have a periodic ajax call. Only this call shouldn't extend the timeout. Please clarify your point regarding basic authentication for this flow. - Niyas
If you use HTTP basic instead of form login, browser will store username and password and will send it with every request. - dur

1 Answers

0
votes

This is how i handled it. Just sharing, it may be of help to someone. Please share any better ways.

Spring Security filter is added as last in the chain.

http.addFilterAfter(new SessionInvalidationFilter(timeOutInMinutes), SwitchUserFilter.class);

It keeps track of a lastUpdatedTime, which gets updated for all calls except for those URLs that needs to be ignored. In case, the differential time is greater than the configured timeout, session gets invalidated.

public class SessionInvalidationFilter extends GenericFilterBean {

    private static final String LASTUPDATEDDATETIME = "LASTUPDATEDDATETIME";

    private static final List<String> ignoredURLs = Arrays.asList("/Notifications/number"); // this is the AJAX URL

    private int timeOutInMinutes = 15;

    public SessionInvalidationFilter(int timeOutInMinutes) {
        this.timeOutInMinutes = timeOutInMinutes;
    }

    @Override
    /**
     * LASTUPDATEDDATETIME is updated for all calls except the ignoredURLs.
     * Session invalidation happens only during the ignoredURLs calls.
     */
    public void doFilter(ServletRequest req, ServletResponse res, FilterChain chain)
            throws IOException, ServletException {
        HttpServletRequest request = (HttpServletRequest) req;
        HttpServletResponse response = (HttpServletResponse) res;

        HttpSession session = request.getSession(false);
        try {
            if (session != null && request.getRequestURI() != null) {
                if (ignoredURLs.contains(request.getRequestURI())) {
                    Object lastUpdatedDateTimeObject = session.getAttribute(LASTUPDATEDDATETIME);
                    if (lastUpdatedDateTimeObject != null) {
                        LocalDateTime lastUpdatedDateTime = (LocalDateTime) lastUpdatedDateTimeObject;
                        long timeInMinutes = ChronoUnit.MINUTES.between(lastUpdatedDateTime, LocalDateTime.now());
                        if (timeInMinutes >= timeOutInMinutes) {
                            log.info("Timing out sessionID:{}", session.getId());
                            session.invalidate();
                            SecurityContextHolder.clearContext();
                        }
                    }
                } else {
                    session.setAttribute(LASTUPDATEDDATETIME, LocalDateTime.now());
                }
            }
        } catch (Exception e) {
            log.error("Exception in SessionInvalidationFilter", e);
        }

        chain.doFilter(request, response);
    }

}