reworked to have pluggable backing store.
This commit is contained in:
Scott Battaglia 2008-01-31 18:33:53 +00:00
parent cfa290756c
commit a11f29ee0f
4 changed files with 125 additions and 40 deletions

View File

@ -0,0 +1,55 @@
/*
* Copyright 2007 The JA-SIG Collaborative. All rights reserved. See license
* distributed with this file and available online at
* http://www.ja-sig.org/products/cas/overview/license/index.html
*/
package org.jasig.cas.client.session;
import java.util.HashMap;
import java.util.Map;
import javax.servlet.http.HttpSession;
/**
* HashMap backed implementation of SessionMappingStorage.
*
* @author Scott Battaglia
* @version $Revision$ $Date$
* @since 3.1
*
*/
public final class HashMapBackedSessionMappingStorage implements
SessionMappingStorage {
/**
* Maps the ID from the CAS server to the Session.
*/
private final Map MANAGED_SESSIONS = new HashMap();
/**
* Maps the Session ID to the key from the CAS Server.
*/
private final Map ID_TO_SESSION_KEY_MAPPING = new HashMap();
public void addSessionById(String mappingId, HttpSession session) {
ID_TO_SESSION_KEY_MAPPING.put(session.getId(), mappingId);
MANAGED_SESSIONS.put(mappingId, session);
}
public void removeBySessionById(String sessionId) {
final String key = (String) ID_TO_SESSION_KEY_MAPPING.get(sessionId);
MANAGED_SESSIONS.remove(key);
ID_TO_SESSION_KEY_MAPPING.remove(sessionId);
}
public HttpSession removeSessionByMappingId(String mappingId) {
final HttpSession session = (HttpSession) MANAGED_SESSIONS.get(mappingId);
if (session != null) {
removeBySessionById(session.getId());
}
return session;
}
}

View File

@ -0,0 +1,41 @@
/*
* Copyright 2007 The JA-SIG Collaborative. All rights reserved. See license
* distributed with this file and available online at
* http://www.ja-sig.org/products/cas/overview/license/index.html
*/
package org.jasig.cas.client.session;
import javax.servlet.http.HttpSession;
/**
* Stores the mapping between sessions and keys to be retrieved later.
*
* @author Scott Battaglia
* @version $Revision$ $Date$
* @since 3.1
*
*/
public interface SessionMappingStorage {
/**
* Remove the HttpSession based on the mappingId.
*
* @param mappingId the id the session is keyed under.
* @return the HttpSession if it exists.
*/
HttpSession removeSessionByMappingId(String mappingId);
/**
* Remove a session by its Id.
* @param sessionId the id of the session.
*/
void removeBySessionById(String sessionId);
/**
* Add a session by its mapping Id.
* @param mappingId the id to map the session to.
* @param session the HttpSession.
*/
void addSessionById(String mappingId, HttpSession session);
}

View File

@ -31,6 +31,8 @@ public final class SingleSignOutFilter extends AbstractConfigurationFilter {
* The name of the artifact parameter. This is used to capture the session identifier.
*/
private String artifactParameterName = "ticket";
private static SessionMappingStorage SESSION_MAPPING_STORAGE = new HashMapBackedSessionMappingStorage();
public void init(final FilterConfig filterConfig) throws ServletException {
setArtifactParameterName(getPropertyFromInitParams(filterConfig, "artifactParameterName", "ticket"));
@ -40,6 +42,7 @@ public final class SingleSignOutFilter extends AbstractConfigurationFilter {
public void init() {
CommonUtils.assertNotNull(this.artifactParameterName, "artifactParameterName cannot be null.");
CommonUtils.assertNotNull(SESSION_MAPPING_STORAGE, "sessionMappingStorage cannote be null.");
}
public void setArtifactParameterName(final String artifactParameterName) {
@ -56,7 +59,11 @@ public final class SingleSignOutFilter extends AbstractConfigurationFilter {
final String sessionIdentifier = XmlUtils.getTextForElement(logoutRequest, "SessionIndex");
if (CommonUtils.isNotBlank(sessionIdentifier)) {
SingleSignOutHttpSessionListener.removeSession(sessionIdentifier);
final HttpSession session = SESSION_MAPPING_STORAGE.removeSessionByMappingId(sessionIdentifier);
if (session != null) {
session.invalidate();
}
return;
}
}
@ -64,12 +71,20 @@ public final class SingleSignOutFilter extends AbstractConfigurationFilter {
final String artifact = request.getParameter(this.artifactParameterName);
final HttpSession session = request.getSession();
if (CommonUtils.isNotBlank(artifact)) {
SingleSignOutHttpSessionListener.addSession(artifact, session);
SESSION_MAPPING_STORAGE.addSessionById(artifact, session);
}
}
filterChain.doFilter(servletRequest, servletResponse);
}
public void setSessionMappingStorage(final SessionMappingStorage storage) {
SESSION_MAPPING_STORAGE = storage;
}
public static SessionMappingStorage getSessionMappingStorage() {
return SESSION_MAPPING_STORAGE;
}
public void destroy() {
// nothing to do

View File

@ -8,16 +8,12 @@ package org.jasig.cas.client.session;
import javax.servlet.http.HttpSession;
import javax.servlet.http.HttpSessionEvent;
import javax.servlet.http.HttpSessionListener;
import java.util.HashMap;
import java.util.Map;
/**
* Listener to detect when an HTTP session is destroyed and remove it from the map of
* managed sessions. Also allows for the programmatic removal of sessions.
* <p>
* Enables the CAS Single Sign out feature.
* <p>
* Note that this class does not scale to multiple machines.
*
* Scott Battaglia
* @version $Revision$ Date$
@ -25,49 +21,27 @@ import java.util.Map;
*/
public final class SingleSignOutHttpSessionListener implements HttpSessionListener {
/**
* Maps the ID from the CAS server to the Session.
*/
private static final Map MANAGED_SESSIONS = new HashMap();
/**
* Maps the Session ID to the key from the CAS Server.
*/
private static final Map ID_TO_SESSION_KEY_MAPPING = new HashMap();
private SessionMappingStorage SESSION_MAPPING_STORAGE;
public void sessionCreated(final HttpSessionEvent event) {
// nothing to do at the moment
}
public void sessionDestroyed(final HttpSessionEvent event) {
if (SESSION_MAPPING_STORAGE == null) {
SESSION_MAPPING_STORAGE = getSessionMappingStorage();
}
final HttpSession session = event.getSession();
final String key = (String) ID_TO_SESSION_KEY_MAPPING.get(session.getId());
MANAGED_SESSIONS.remove(key);
ID_TO_SESSION_KEY_MAPPING.remove(session.getId());
}
public static void addSession(final String key, final HttpSession value) {
ID_TO_SESSION_KEY_MAPPING.put(value.getId(), key);
MANAGED_SESSIONS.put(key, value);
SESSION_MAPPING_STORAGE.removeBySessionById(session.getId());
}
/**
* Method to remove the session from the mapping based on the key returned from the
* CAS server.
*
* @param key the key to look up in the map of sessions.
* Obtains a {@link SessionMappingStorage} object. Assumes this method will always return the same
* instance of the object. It assumes this because it generally lazily calls the method.
*
* @return the SessionMappingStorage
*/
public static void removeSession(final String key) {
final HttpSession session = (HttpSession) MANAGED_SESSIONS.get(key);
if (session == null) {
return;
}
final String id = session.getId();
MANAGED_SESSIONS.remove(key);
ID_TO_SESSION_KEY_MAPPING.remove(id);
session.invalidate();
protected static SessionMappingStorage getSessionMappingStorage() {
return SingleSignOutFilter.getSessionMappingStorage();
}
}