views:

44

answers:

1

Hi all I was designated to implement a security requierement to mimic "messenger like" authentication, for example: if a user first logs in, then another user tries to log in with the same username, this new user will be prompted to "kick" the previously loged user and the system should invalidate the first user's web session, the web app is running on tomcat 6, i was taking a look at HTTPSessionContext but its now deprecated, is there an alternative or should i go and implement something myself using a HTTPSessionListener ?

A: 

HTTPSessionListener might not work because you don't have access to the user principal there. I have done something similar using a filter (without the invalidation of the session). This is a striped down version of what I did with some code that might work for your situation (haven't tested it):

public class ApplicationFilter implements Filter {

    private Map<String, HttpSession> sessions = new HashMap<String, HttpSession>();

    public void init(FilterConfig config) throws ServletException {
    }

    public void destroy() {
    }

    public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain chain) 
        throws IOException, ServletException {

        HttpServletRequest request = (HttpServletRequest) servletRequest;
        HttpServletResponse response = (HttpServletResponse) servletResponse;
        Principal principal = request.getUserPrincipal();
        HttpSession session = request.getSession();

        if (principal != null && session.getAttribute("THE_PRINCIPAL") == null) {

            // update the current session
            session.setAttribute("THE_PRINCIPAL", session);

            // get the username from the principal
            // (assumes you using container based authentication)
            String username = principal.getName();

            // invalidate previous session if it exists
            HttpSession s = sessions.get(username);
            if (s != null)
                s.invalidate();

            // register this session as the one for the user
            sessions.put(username, session);

        }

        chain.doFilter(servletRequest, servletResponse);

    }

}
rmarimon
I guess this will work, just one question though, would the container create a new instance of my filter over a period of time? or it will use the same instance all the time until the container is stoped?, if so should i make the sessions map static and make the changes to it inside a synchronized block ?
Harima555
I think it creates a new instance every time it needs one. It might also pool instances so better is to created a static map. Make it a ConcurrentHashMap which deals with all the synchronization automatically.http://download.oracle.com/javase/6/docs/api/java/util/concurrent/ConcurrentHashMap.html
rmarimon
ok willl take your advice =)
Harima555