I’m working on a grails web application with spring security. I have a requirement for forcing a session expiration after a fixed set of time even if the session is active.
I think I can add filter and check for each request's last login time:
if (CURRENT_TIME - LAST_LOGIN > ABSOLUTE_SESSIO EXPIRATION) then FORCE LOGOUT
But the problem is that the session is still active on the server until the user makes request.
Is this possible to destroy session immediately after N minutes even if user is using the system?
I was researching tomcat session management and how spring security handles it, but didn’t find any useful information.
Could anybody point me at some example? Has anybody implemented something similar?
[Edit: An idea for killing the session at a specific time decided by the login time would be use a task scheduler like Quartz to schedule a task that is passed the session as a parameter. You could then schedule it to call a job that performs a session.invalidate()
at a specific point in time. The task would be scheduled at login time.]
This is how I would do it, but it doesn't kill the session at the specific time you want. It relies on the user making a request. It's not fool proof, but you could make the application poll the site every minute or so via an AJAX call perhaps.
Set a session activation time on the users session. Then add a filter to the web application for all incoming requests that checks the (activation period + the allowed time) exceeds the current time. If it does not, then call session.invalidate();
i.e. on login
HttpSession session = request.getSession();
session.setAttribute( "activation-time", System.currentTimeMillis() );
Then add a filter to web.xml
<filter>
<filter-name>SessionFilter</filter-name>
<filter-class>com.something.SessionFilter</filter-class>
<init-param>
<param-name>max-period</param-name>
<param-value>60000</param-value>
</init-param>
</filter>
<filter-mapping>
<filter-name>SessionFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
The filter would be something along the lines of...
package com.something;
import java.io.IOException;
import java.util.Date;
import javax.servlet.Filter;
import javax.servlet.FilterChain;
import javax.servlet.FilterConfig;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpSession;
public class SessionFilter implements Filter {
private long maxPeriod;
public void doFilter(ServletRequest req, ServletResponse res, FilterChain chain) throws IOException, ServletException {
HttpServletRequest request = (HttpServletRequest) req;
HttpSession session = request.getSession( false );
if ( session != null ) {
long activated = (long) session.getAttribute( "activation-time" );
if ( System.currentTimeMillis() > ( activated + maxPeriod ) ) {
session.invalidate();
}
}
chain.doFilter(req, res);
}
public void init(FilterConfig config) throws ServletException {
//Get init parameter
if ( config.getInitParameter("max-period") == null ) {
throw new IllegalStateException( "max-period must be provided" );
}
maxPeriod = new Long( config.getInitParameter("max-period") );
}
public void destroy() {
//add code to release any resource
}
}
If you need to invoke something when the session is invalidated then you can write a HttpSessionListener
and configure in web.xml also.