All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.jwall.web.audit.session.AbstractSessionTracker Maven / Gradle / Ivy

/*
 *  Copyright (C) 2007-2014 Christian Bockermann 
 *
 *  This file is part of the  web-audit  library.
 *
 *  web-audit library is free software; you can redistribute it and/or modify
 *  it under the terms of the GNU General Public License as published by
 *  the Free Software Foundation; either version 3 of the License, or
 *  (at your option) any later version.
 *
 *  The  web-audit  library is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *  GNU General Public License for more details.
 *
 *  You should have received a copy of the GNU General Public License
 *  along with this program.  If not, see .
 *
 */
package org.jwall.web.audit.session;

import java.util.Collection;
import java.util.HashMap;
import java.util.LinkedList;
import java.util.List;
import java.util.Vector;

import org.jwall.web.audit.AuditEvent;
import org.jwall.web.audit.ModSecurity;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
 * 
 * This class is an abstract implementation of a simple session tracker and
 * provides the basis for the tracker HeuristicSessionTracker and
 * CookieSessionTracker.
 * 
 * @author Christian Bockermann <[email protected]>
 * 
 */
public abstract class AbstractSessionTracker implements SessionTracker {
	static Logger log = LoggerFactory.getLogger(AbstractSessionTracker.class);
	protected long sessionTimeOut = 2 * 3600 * 1000;
	protected HashMap activeSessions;
	protected List timedOutSessions;
	protected int type = -1;
	boolean strictSessions = true;

	/**
	 * 
	 * This creates a new instance of this class which is based on the default
	 * timeout of 2 hours ( = 7200000 ms ).
	 * 
	 */
	public AbstractSessionTracker() {
		super();
		activeSessions = new HashMap();
		timedOutSessions = new LinkedList();
	}

	/**
	 * This initializes the tracker with the given session-timeout.
	 * 
	 * @param timeout
	 *            The session-timeout in seconds.
	 */
	public AbstractSessionTracker(long timeout) {
		this();
		setSessionTimeOut(timeout);
	}

	/**
	 * 
	 * This method tracks an AuditEvent object and creates a session if none
	 * existed yet. Otherwise the existing session is touched.
	 * 
	 * @param event
	 *            The AuditEvent instance that is to be associated with a
	 *            session.
	 * 
	 */
	public void eventArrived(AuditEvent event) {
		String key = extractKey(event);
		if (key == null) {
			log.debug("Ignoring event without session-key {}",
					event.getEventId());
			return;
		} else
			log.trace("Found session-id '{}'!", key);

		Session s = activeSessions.get(key);
		if (s == null) {
			log.debug("creating a new session ({}): {}", activeSessions
					.keySet().size(), key);

			Session sess = new Session(type, key, event);
			activeSessions.put(key, sess);

			event.setSessionId(sess.getId());
			event.set(ModSecurity.SESSIONID, s.getId());
		} else {

			if (isExpired(s, event)) {

				expireSession(s);

				s = this.createSession(event);
				if (s == null)
					return;
				event.setSessionId(s.getId());
				event.set(ModSecurity.SESSIONID, s.getId());
			} else {
				s.addEvent(event);
				event.setSessionId(s.getId());
				event.set(ModSecurity.SESSIONID, s.getId());
			}
		}
	}

	public void eventsArrived(Collection events) {
		for (AuditEvent evt : events)
			eventArrived(evt);
	}

	/**
	 * Remove the session from the hash of active sessions and store it in the
	 * list of timed-out sessions.
	 * 
	 * @param s
	 *            The session to expire.
	 */
	protected void expireSession(Session s) {
		activeSessions.remove(s.getId());
		timedOutSessions.add(s);
	}

	/**
	 * This method returns the session with the given session-id.
	 * 
	 * @param sessionId
	 *            The id of the session that is to be retrieved.
	 * @return The appopriate session if it is still active or null
	 *         if the session is inactive or does not exist at all.
	 */
	public Session getSession(String sessionId) {
		return activeSessions.get(sessionId);
	}

	/*
	 * 
	 * This method is used to create a new session.
	 */
	private Session createSession(AuditEvent event) {
		String key = extractKey(event);
		if (key == null)
			return null;

		Session s = activeSessions.get(key);

		if (s != null && isExpired(s, event)) {
			activeSessions.remove(key);
			timedOutSessions.add(s);
			s = null;
		}

		if (s == null) {
			s = new Session(type, key, event);
			event.setSessionId(s.getId());
			activeSessions.put(key, s);
		}

		return s;
	}

	/**
	 * 
	 * This method returns all the sessions (active and timed-out) that have
	 * been created by the session-tracker.
	 * 
	 * @return A collection of session instances.
	 * 
	 */
	public Collection getSessions() {
		Collection v = new Vector();

		v.addAll(timedOutSessions);
		v.addAll(activeSessions.values());

		return v;
	}

	/**
	 * 
	 * This method simply resets the session-tracker to the initial state which
	 * holds no sessions.
	 * 
	 */
	public void reset() {
		activeSessions.clear();
		timedOutSessions.clear();
	}

	/**
	 * 
	 * This method is used to check a session for expiration according to the
	 * date of the given audit-event.
	 * 
	 * @param s
	 *            The session that is to be checked.
	 * @param event
	 *            The event which defines the current date.
	 * @return true if the sessions' last access-time is no longer
	 *         that a period of X seconds away from the events date. Here X is
	 *         the session-timeout defined for this session-tracker.
	 * 
	 */
	public boolean isExpired(Session s, AuditEvent event) {
		return event.getDate().getTime() - s.lastAccessed().getTime() > sessionTimeOut;
	}

	/**
	 * This method is used to set the session-timeout. Modification of the
	 * timeout does not affect any of the sessions created so far.
	 * 
	 * @param s
	 *            The number of seconds after which a session is to be timed
	 *            out.
	 */
	public void setSessionTimeOut(long s) {
		sessionTimeOut = s;
	}

	/**
	 * Returns the session-timeout that is used by this tracker.
	 * 
	 * @return The number of seconds that a session is kept active without any
	 *         events related to it.
	 */
	public long getSessionTimeOut() {
		return sessionTimeOut;
	}

	/**
	 * 
	 * In a strict session the session-id is presumed to be created by the
	 * server-side application. Thus only sessions for which the server
	 * responded with a session identifier are assumed to be valid. This
	 * prevents the tracker from trusting any requests of a simple
	 * session-guessing attack.
	 * 
	 * @param b
	 *            Wether this tracker should only track strict sessions.
	 * 
	 */
	public void setStrictSessions(boolean b) {
		strictSessions = b;
	}

	/**
	 * 
	 * @return Wether the tracker is using strict sessioning only.
	 */
	public boolean usesStrictSessions() {
		return strictSessions;
	}

	/**
	 * This method extracts the key-feature from an event which is used to
	 * identify the session that this event is related to. This might be the
	 * remote-address, a special request-parameter or a cookie.
	 * 
	 * @param evt
	 *            The event from which to extract the session-id.
	 * @return A string that identifies the session associated with this event.
	 */
	public abstract String extractKey(AuditEvent evt);

	/**
	 * This method returns a string of all events grouped by their session-id.
	 * 
	 * @return A string holding all sessions
	 */
	public String toString() {
		StringBuffer sb = new StringBuffer();

		for (Session s : getSessions()) {
			sb.append("-------SESSION: " + s.getId()
					+ "---------------------------\n");
		}

		return sb.toString();
	}
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy