craigmcc 01/07/28 20:43:54
Modified: catalina/src/share/org/apache/catalina HttpRequest.java
Session.java
catalina/src/share/org/apache/catalina/authenticator
AuthenticatorBase.java FormAuthenticator.java
SingleSignOn.java
catalina/src/share/org/apache/catalina/connector
HttpRequestBase.java
catalina/src/share/org/apache/catalina/core
ContainerBase.java
catalina/src/share/org/apache/catalina/session
StandardSession.java
Added: catalina/src/share/org/apache/catalina SessionEvent.java
SessionListener.java
Log:
Enhance support for "single sign on" to also support "single sign off" in
conformance to the additional spec requirements listed in Servlet Spec 2.3
PFD3, Section 12.5.3.1, page 90. In particular, under the following
circumstances:
- Administrator has configured SingleSignOnValve on a virtual host
- Web applications on this virtual host are configured for form-based
login
- User has logged in to one of the apps (which also grants them access
to the protected areas of the other apps, because of the single sign
on support)
- A session in one of the logged-on-to apps is invalidated or times out
then, all sessions in all apps to which the user has been logged on will
be invalidated. The next request from this user for a protected resource
in any of the apps will cause the user to be reauthenticated.
Rationale: Consider a Yahoo-like portal server, with multiple
applications (such as mail and chat) implemented as separate web apps
under management of the single sign on facility. If the user accesses
both mail and chat, and then logs out of mail, he or she will expect the
login to the chat application to be terminated as well. Otherwise, the
next person to use this browser (say, at an Internet cafe) would have
access to the previous user's session in the chat application -- and, by
virtue of single sign on, access to all their other applications as well.
Revision Changes Path
1.3 +18 -4
jakarta-tomcat-4.0/catalina/src/share/org/apache/catalina/HttpRequest.java
Index: HttpRequest.java
===================================================================
RCS file:
/home/cvs/jakarta-tomcat-4.0/catalina/src/share/org/apache/catalina/HttpRequest.java,v
retrieving revision 1.2
retrieving revision 1.3
diff -u -r1.2 -r1.3
--- HttpRequest.java 2000/09/25 21:46:30 1.2
+++ HttpRequest.java 2001/07/29 03:43:54 1.3
@@ -1,7 +1,7 @@
/*
- * $Header:
/home/cvs/jakarta-tomcat-4.0/catalina/src/share/org/apache/catalina/HttpRequest.java,v
1.2 2000/09/25 21:46:30 craigmcc Exp $
- * $Revision: 1.2 $
- * $Date: 2000/09/25 21:46:30 $
+ * $Header:
/home/cvs/jakarta-tomcat-4.0/catalina/src/share/org/apache/catalina/HttpRequest.java,v
1.3 2001/07/29 03:43:54 craigmcc Exp $
+ * $Revision: 1.3 $
+ * $Date: 2001/07/29 03:43:54 $
*
* ====================================================================
*
@@ -76,7 +76,7 @@
* produce the corresponding <code>HttpResponse</code>.
*
* @author Craig R. McClanahan
- * @version $Revision: 1.2 $ $Date: 2000/09/25 21:46:30 $
+ * @version $Revision: 1.3 $ $Date: 2001/07/29 03:43:54 $
*/
public interface HttpRequest extends Request {
@@ -147,6 +147,12 @@
/**
+ * Return the single sign on identifier this request is associated with.
+ */
+ public String getSsoId();
+
+
+ /**
* Set the authentication type used for this request, if any; otherwise
* set the type to <code>null</code>. Typical values are "BASIC",
* "DIGEST", or "SSL".
@@ -239,6 +245,14 @@
* @param path The servlet path
*/
public void setServletPath(String path);
+
+
+ /**
+ * Set the single sign on identifier this request is associated with.
+ *
+ * @param ssoId The new SSO identifier (if any)
+ */
+ public void setSsoId(String ssoId);
/**
1.4 +32 -5
jakarta-tomcat-4.0/catalina/src/share/org/apache/catalina/Session.java
Index: Session.java
===================================================================
RCS file:
/home/cvs/jakarta-tomcat-4.0/catalina/src/share/org/apache/catalina/Session.java,v
retrieving revision 1.3
retrieving revision 1.4
diff -u -r1.3 -r1.4
--- Session.java 2001/04/08 07:55:46 1.3
+++ Session.java 2001/07/29 03:43:54 1.4
@@ -1,13 +1,13 @@
/*
- * $Header:
/home/cvs/jakarta-tomcat-4.0/catalina/src/share/org/apache/catalina/Session.java,v 1.3
2001/04/08 07:55:46 kief Exp $
- * $Revision: 1.3 $
- * $Date: 2001/04/08 07:55:46 $
+ * $Header:
/home/cvs/jakarta-tomcat-4.0/catalina/src/share/org/apache/catalina/Session.java,v 1.4
2001/07/29 03:43:54 craigmcc Exp $
+ * $Revision: 1.4 $
+ * $Date: 2001/07/29 03:43:54 $
*
* ====================================================================
*
* The Apache Software License, Version 1.1
*
- * Copyright (c) 1999 The Apache Software Foundation. All rights
+ * Copyright (c) 1999-2001 The Apache Software Foundation. All rights
* reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -77,12 +77,27 @@
* between requests for a particular user of a web application.
*
* @author Craig R. McClanahan
- * @version $Revision: 1.3 $ $Date: 2001/04/08 07:55:46 $
+ * @version $Revision: 1.4 $ $Date: 2001/07/29 03:43:54 $
*/
public interface Session {
+ // ----------------------------------------------------- Manifest Constants
+
+
+ /**
+ * The SessionEvent event type when a session is created.
+ */
+ public static final String SESSION_CREATED_EVENT = "createSession";
+
+
+ /**
+ * The SessionEvent event type when a session is destroyed.
+ */
+ public static final String SESSION_DESTROYED_EVENT = "destroySession";
+
+
// ------------------------------------------------------------- Properties
@@ -242,6 +257,12 @@
/**
+ * Add a session event listener to this component.
+ */
+ public void addSessionListener(SessionListener listener);
+
+
+ /**
* Perform the internal processing required to invalidate this session,
* without triggering an exception if the session has already expired.
*/
@@ -253,6 +274,12 @@
* preparation for reuse of this object.
*/
public void recycle();
+
+
+ /**
+ * Remove a session event listener from this component.
+ */
+ public void removeSessionListener(SessionListener listener);
}
1.1
jakarta-tomcat-4.0/catalina/src/share/org/apache/catalina/SessionEvent.java
Index: SessionEvent.java
===================================================================
/*
* $Header:
/home/cvs/jakarta-tomcat-4.0/catalina/src/share/org/apache/catalina/SessionEvent.java,v
1.1 2001/07/29 03:43:54 craigmcc Exp $
* $Revision: 1.1 $
* $Date: 2001/07/29 03:43:54 $
*
* ====================================================================
*
* The Apache Software License, Version 1.1
*
* Copyright (c) 1999-2001 The Apache Software Foundation. All rights
* reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
*
* 3. The end-user documentation included with the redistribution, if
* any, must include the following acknowlegement:
* "This product includes software developed by the
* Apache Software Foundation (http://www.apache.org/)."
* Alternately, this acknowlegement may appear in the software itself,
* if and wherever such third-party acknowlegements normally appear.
*
* 4. The names "The Jakarta Project", "Tomcat", and "Apache Software
* Foundation" must not be used to endorse or promote products derived
* from this software without prior written permission. For written
* permission, please contact [EMAIL PROTECTED]
*
* 5. Products derived from this software may not be called "Apache"
* nor may "Apache" appear in their names without prior written
* permission of the Apache Group.
*
* THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
* ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
* USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
* OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
* ====================================================================
*
* This software consists of voluntary contributions made by many
* individuals on behalf of the Apache Software Foundation. For more
* information on the Apache Software Foundation, please see
* <http://www.apache.org/>.
*
* [Additional notices, if required by prior licensing conditions]
*
*/
package org.apache.catalina;
import java.util.EventObject;
/**
* General event for notifying listeners of significant changes on a Session.
*
* @author Craig R. McClanahan
* @version $Revision: 1.1 $ $Date: 2001/07/29 03:43:54 $
*/
public final class SessionEvent
extends EventObject {
/**
* The event data associated with this event.
*/
private Object data = null;
/**
* The Session on which this event occurred.
*/
private Session session = null;
/**
* The event type this instance represents.
*/
private String type = null;
/**
* Construct a new SessionEvent with the specified parameters.
*
* @param session Session on which this event occurred
* @param type Event type
* @param data Event data
*/
public SessionEvent(Session session, String type, Object data) {
super(session);
this.session = session;
this.type = type;
this.data = data;
}
/**
* Return the event data of this event.
*/
public Object getData() {
return (this.data);
}
/**
* Return the Session on which this event occurred.
*/
public Session getSession() {
return (this.session);
}
/**
* Return the event type of this event.
*/
public String getType() {
return (this.type);
}
/**
* Return a string representation of this event.
*/
public String toString() {
return ("SessionEvent['" + getSession() + "','" +
getType() + "']");
}
}
1.1
jakarta-tomcat-4.0/catalina/src/share/org/apache/catalina/SessionListener.java
Index: SessionListener.java
===================================================================
/*
* $Header:
/home/cvs/jakarta-tomcat-4.0/catalina/src/share/org/apache/catalina/SessionListener.java,v
1.1 2001/07/29 03:43:54 craigmcc Exp $
* $Revision: 1.1 $
* $Date: 2001/07/29 03:43:54 $
*
* ====================================================================
*
* The Apache Software License, Version 1.1
*
* Copyright (c) 1999-2001 The Apache Software Foundation. All rights
* reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
*
* 3. The end-user documentation included with the redistribution, if
* any, must include the following acknowlegement:
* "This product includes software developed by the
* Apache Software Foundation (http://www.apache.org/)."
* Alternately, this acknowlegement may appear in the software itself,
* if and wherever such third-party acknowlegements normally appear.
*
* 4. The names "The Jakarta Project", "Tomcat", and "Apache Software
* Foundation" must not be used to endorse or promote products derived
* from this software without prior written permission. For written
* permission, please contact [EMAIL PROTECTED]
*
* 5. Products derived from this software may not be called "Apache"
* nor may "Apache" appear in their names without prior written
* permission of the Apache Group.
*
* THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
* ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
* USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
* OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
* ====================================================================
*
* This software consists of voluntary contributions made by many
* individuals on behalf of the Apache Software Foundation. For more
* information on the Apache Software Foundation, please see
* <http://www.apache.org/>.
*
* [Additional notices, if required by prior licensing conditions]
*
*/
package org.apache.catalina;
import java.util.EventObject;
/**
* Interface defining a listener for significant Session generated events.
*
* @author Craig R. McClanahan
* @version $Revision: 1.1 $ $Date: 2001/07/29 03:43:54 $
*/
public interface SessionListener {
/**
* Acknowledge the occurrence of the specified event.
*
* @param event SessionEvent that has occurred
*/
public void sessionEvent(SessionEvent event);
}
1.20 +21 -4
jakarta-tomcat-4.0/catalina/src/share/org/apache/catalina/authenticator/AuthenticatorBase.java
Index: AuthenticatorBase.java
===================================================================
RCS file:
/home/cvs/jakarta-tomcat-4.0/catalina/src/share/org/apache/catalina/authenticator/AuthenticatorBase.java,v
retrieving revision 1.19
retrieving revision 1.20
diff -u -r1.19 -r1.20
--- AuthenticatorBase.java 2001/07/22 20:09:19 1.19
+++ AuthenticatorBase.java 2001/07/29 03:43:54 1.20
@@ -1,7 +1,7 @@
/*
- * $Header:
/home/cvs/jakarta-tomcat-4.0/catalina/src/share/org/apache/catalina/authenticator/AuthenticatorBase.java,v
1.19 2001/07/22 20:09:19 pier Exp $
- * $Revision: 1.19 $
- * $Date: 2001/07/22 20:09:19 $
+ * $Header:
/home/cvs/jakarta-tomcat-4.0/catalina/src/share/org/apache/catalina/authenticator/AuthenticatorBase.java,v
1.20 2001/07/29 03:43:54 craigmcc Exp $
+ * $Revision: 1.20 $
+ * $Date: 2001/07/29 03:43:54 $
*
* ====================================================================
*
@@ -121,7 +121,7 @@
* requests. Requests of any other type will simply be passed through.
*
* @author Craig R. McClanahan
- * @version $Revision: 1.19 $ $Date: 2001/07/22 20:09:19 $
+ * @version $Revision: 1.20 $ $Date: 2001/07/29 03:43:54 $
*/
@@ -609,6 +609,22 @@
/**
+ * Associate the specified single sign on identifier with the
+ * specified Session.
+ *
+ * @param ssoId Single sign on identifier
+ * @param session Session to be associated
+ */
+ protected void associate(String ssoId, Session session) {
+
+ if (sso == null)
+ return;
+ sso.associate(ssoId, session);
+
+ }
+
+
+ /**
* Authenticate the user making this request, based on the specified
* login configuration. Return <code>true</code> if any specified
* constraint has been satisfied, or <code>false</code> if we have
@@ -970,6 +986,7 @@
// Register this principal with our SSO valve
sso.register(value, principal, authType);
+ request.setSsoId(value);
}
1.14 +10 -23
jakarta-tomcat-4.0/catalina/src/share/org/apache/catalina/authenticator/FormAuthenticator.java
Index: FormAuthenticator.java
===================================================================
RCS file:
/home/cvs/jakarta-tomcat-4.0/catalina/src/share/org/apache/catalina/authenticator/FormAuthenticator.java,v
retrieving revision 1.13
retrieving revision 1.14
diff -u -r1.13 -r1.14
--- FormAuthenticator.java 2001/07/26 19:11:36 1.13
+++ FormAuthenticator.java 2001/07/29 03:43:54 1.14
@@ -1,7 +1,7 @@
/*
- * $Header:
/home/cvs/jakarta-tomcat-4.0/catalina/src/share/org/apache/catalina/authenticator/FormAuthenticator.java,v
1.13 2001/07/26 19:11:36 craigmcc Exp $
- * $Revision: 1.13 $
- * $Date: 2001/07/26 19:11:36 $
+ * $Header:
/home/cvs/jakarta-tomcat-4.0/catalina/src/share/org/apache/catalina/authenticator/FormAuthenticator.java,v
1.14 2001/07/29 03:43:54 craigmcc Exp $
+ * $Revision: 1.14 $
+ * $Date: 2001/07/29 03:43:54 $
*
* ====================================================================
*
@@ -88,7 +88,7 @@
* Authentication, as described in the Servlet API Specification, Version 2.2.
*
* @author Craig R. McClanahan
- * @version $Revision: 1.13 $ $Date: 2001/07/26 19:11:36 $
+ * @version $Revision: 1.14 $ $Date: 2001/07/29 03:43:54 $
*/
public final class FormAuthenticator
@@ -152,6 +152,9 @@
if (debug >= 1)
log("Already authenticated '" +
principal.getName() + "'");
+ String ssoId = request.getSsoId();
+ if (ssoId != null)
+ associate(ssoId, getSession(request, true));
return (true);
}
@@ -164,6 +167,9 @@
principal = (Principal)
session.getSession().getAttribute(Constants.FORM_PRINCIPAL);
register(request, response, principal, Constants.FORM_METHOD);
+ String ssoId = request.getSsoId();
+ if (ssoId != null)
+ associate(ssoId, session);
if (restoreRequest(request, session)) {
if (debug >= 1)
log("Proceed to restored request");
@@ -244,25 +250,6 @@
log("Redirecting to '" + requestURI + "'");
hres.sendRedirect(hres.encodeRedirectURL(requestURI));
return (false);
-
- // Restore this request and redirect to the original request URI
- /*
- session = getSession(request, true);
- if (debug >= 1)
- log("restore request from session '" + session.getId() + "'");
- register(request, response, principal, Constants.FORM_METHOD);
- if (restoreRequest(request, session)) {
- if (debug >= 1)
- log("Proceed to restored request");
- return (true); // Perform the original request
- } else {
- if (debug >= 1)
- log("Restore of original request failed");
- hres.sendError(HttpServletResponse.SC_BAD_REQUEST);
- // hres.flushBuffer();
- return (false);
- }
- */
}
1.7 +245 -38
jakarta-tomcat-4.0/catalina/src/share/org/apache/catalina/authenticator/SingleSignOn.java
Index: SingleSignOn.java
===================================================================
RCS file:
/home/cvs/jakarta-tomcat-4.0/catalina/src/share/org/apache/catalina/authenticator/SingleSignOn.java,v
retrieving revision 1.6
retrieving revision 1.7
diff -u -r1.6 -r1.7
--- SingleSignOn.java 2001/07/22 20:09:19 1.6
+++ SingleSignOn.java 2001/07/29 03:43:54 1.7
@@ -1,7 +1,7 @@
/*
- * $Header:
/home/cvs/jakarta-tomcat-4.0/catalina/src/share/org/apache/catalina/authenticator/SingleSignOn.java,v
1.6 2001/07/22 20:09:19 pier Exp $
- * $Revision: 1.6 $
- * $Date: 2001/07/22 20:09:19 $
+ * $Header:
/home/cvs/jakarta-tomcat-4.0/catalina/src/share/org/apache/catalina/authenticator/SingleSignOn.java,v
1.7 2001/07/29 03:43:54 craigmcc Exp $
+ * $Revision: 1.7 $
+ * $Date: 2001/07/29 03:43:54 $
*
* ====================================================================
*
@@ -71,14 +71,23 @@
import javax.servlet.ServletException;
import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
import org.apache.catalina.Container;
import org.apache.catalina.HttpRequest;
import org.apache.catalina.HttpResponse;
+import org.apache.catalina.Lifecycle;
+import org.apache.catalina.LifecycleEvent;
+import org.apache.catalina.LifecycleException;
+import org.apache.catalina.LifecycleListener;
import org.apache.catalina.Logger;
import org.apache.catalina.Request;
import org.apache.catalina.Response;
+import org.apache.catalina.Session;
+import org.apache.catalina.SessionEvent;
+import org.apache.catalina.SessionListener;
import org.apache.catalina.ValveContext;
import org.apache.catalina.valves.ValveBase;
+import org.apache.catalina.util.LifecycleSupport;
import org.apache.catalina.util.StringManager;
@@ -100,11 +109,12 @@
* </ul>
*
* @author Craig R. McClanahan
- * @version $Revision: 1.6 $ $Date: 2001/07/22 20:09:19 $
+ * @version $Revision: 1.7 $ $Date: 2001/07/29 03:43:54 $
*/
public class SingleSignOn
- extends ValveBase {
+ extends ValveBase
+ implements Lifecycle, SessionListener {
// ----------------------------------------------------- Instance Variables
@@ -131,12 +141,31 @@
/**
+ * The lifecycle event support for this component.
+ */
+ protected LifecycleSupport lifecycle = new LifecycleSupport(this);
+
+
+ /**
+ * The cache of single sign on identifiers, keyed by the Session that is
+ * associated with them.
+ */
+ protected HashMap reverse = new HashMap();
+
+
+ /**
* The string manager for this package.
*/
protected final static StringManager sm =
StringManager.getManager(Constants.Package);
+ /**
+ * Component started flag.
+ */
+ protected boolean started = false;
+
+
// ------------------------------------------------------------- Properties
@@ -162,6 +191,113 @@
}
+ // ------------------------------------------------------ Lifecycle Methods
+
+
+ /**
+ * Add a lifecycle event listener to this component.
+ *
+ * @param listener The listener to add
+ */
+ public void addLifecycleListener(LifecycleListener listener) {
+
+ lifecycle.addLifecycleListener(listener);
+
+ }
+
+
+ /**
+ * Remove a lifecycle event listener from this component.
+ *
+ * @param listener The listener to remove
+ */
+ public void removeLifecycleListener(LifecycleListener listener) {
+
+ lifecycle.removeLifecycleListener(listener);
+
+ }
+
+
+ /**
+ * Prepare for the beginning of active use of the public methods of this
+ * component. This method should be called after <code>configure()</code>,
+ * and before any of the public methods of the component are utilized.
+ *
+ * @exception IllegalStateException if this component has already been
+ * started
+ * @exception LifecycleException if this component detects a fatal error
+ * that prevents this component from being used
+ */
+ public void start() throws LifecycleException {
+
+ // Validate and update our current component state
+ if (started)
+ throw new LifecycleException
+ (sm.getString("authenticator.alreadyStarted"));
+ lifecycle.fireLifecycleEvent(START_EVENT, null);
+ started = true;
+
+ if (debug >= 1)
+ log("Started");
+
+ }
+
+
+ /**
+ * Gracefully terminate the active use of the public methods of this
+ * component. This method should be the last one called on a given
+ * instance of this component.
+ *
+ * @exception IllegalStateException if this component has not been started
+ * @exception LifecycleException if this component detects a fatal error
+ * that needs to be reported
+ */
+ public void stop() throws LifecycleException {
+
+ // Validate and update our current component state
+ if (!started)
+ throw new LifecycleException
+ (sm.getString("authenticator.notStarted"));
+ lifecycle.fireLifecycleEvent(STOP_EVENT, null);
+ started = false;
+
+ if (debug >= 1)
+ log("Stopped");
+
+ }
+
+
+ // ------------------------------------------------ SessionListener Methods
+
+
+ /**
+ * Acknowledge the occurrence of the specified event.
+ *
+ * @param event SessionEvent that has occurred
+ */
+ public void sessionEvent(SessionEvent event) {
+
+ // We only care about session destroyed events
+ if (!Session.SESSION_DESTROYED_EVENT.equals(event.getType()))
+ return;
+
+ // Look up the single session id associated with this session (if any)
+ Session session = event.getSession();
+ if (debug >= 1)
+ log("Process session destroyed on " + session);
+ String ssoId = null;
+ synchronized (reverse) {
+ ssoId = (String) reverse.get(session);
+ }
+ if (ssoId == null)
+ return;
+
+ // Deregister this single session id, invalidating associated sessions
+ deregister(ssoId);
+
+ }
+
+
// ---------------------------------------------------------- Valve Methods
@@ -196,10 +332,13 @@
context.invokeNext(request, response);
return;
}
-
- // Has a valid user already been authenticated?
HttpServletRequest hreq =
(HttpServletRequest) request.getRequest();
+ HttpServletResponse hres =
+ (HttpServletResponse) response.getResponse();
+ ((HttpRequest) request).setSsoId(null);
+
+ // Has a valid user already been authenticated?
if (debug >= 1)
log("Process request for '" + hreq.getRequestURI() + "'");
if (hreq.getUserPrincipal() != null) {
@@ -232,18 +371,21 @@
// Look up the cached Principal associated with this cookie value
if (debug >= 1)
- log(" Checking for cached principal");
+ log(" Checking for cached principal for " + cookie.getValue());
SingleSignOnEntry entry = lookup(cookie.getValue());
if (entry != null) {
if (debug >= 1)
log(" Found cached principal '" +
entry.principal.getName() + "' with auth type '" +
entry.authType + "'");
+ ((HttpRequest) request).setSsoId(cookie.getValue());
((HttpRequest) request).setAuthType(entry.authType);
((HttpRequest) request).setUserPrincipal(entry.principal);
} else {
if (debug >= 1)
- log(" No cached principal found");
+ log(" No cached principal found, erasing SSO cookie");
+ cookie.setMaxAge(0);
+ hres.addCookie(cookie);
}
// Invoke the next Valve in our pipeline
@@ -256,53 +398,101 @@
/**
- * Deregister the specified cookie value for the single sign on cookie.
+ * Return a String rendering of this object.
+ */
+ public String toString() {
+
+ StringBuffer sb = new StringBuffer("SingleSignOn[");
+ sb.append(container.getName());
+ sb.append("]");
+ return (sb.toString());
+
+ }
+
+
+ // -------------------------------------------------------- Package Methods
+
+
+ /**
+ * Associate the specified single sign on identifier with the
+ * specified Session.
*
- * @param cookie Cookie value for the single sign on cookie to deregister
+ * @param ssoId Single sign on identifier
+ * @param session Session to be associated
*/
- public void deregister(String cookie) {
+ void associate(String ssoId, Session session) {
- log("Deregistering cookie value '" + cookie + "'");
+ if (debug >= 1)
+ log("Associate sso id " + ssoId + " with session " + session);
- synchronized (cache) {
- cache.remove(cookie);
+ SingleSignOnEntry sso = lookup(ssoId);
+ if (sso != null)
+ sso.addSession(this, session);
+ synchronized (reverse) {
+ reverse.put(session, ssoId);
}
}
/**
- * Register the specified Principal as being associated with the specified
- * value for the single sign on cookie.
+ * Deregister the specified single sign on identifier, and invalidate
+ * any associated sessions.
*
- * @param cookie Cookie value for the single sign on cookie
- * @param principal Associated user principal that is identified
- * @param authType Authentication type used to authenticate this
- * user principal
+ * @param ssoId Single sign on identifier to deregister
*/
- public void register(String cookie, Principal principal, String authType) {
+ void deregister(String ssoId) {
if (debug >= 1)
- log("Registering cookie value '" + cookie + "' for user '" +
- principal.getName() + "' with auth type '" + authType + "'");
+ log("Deregistering sso id '" + ssoId + "'");
+ // Look up and remove the corresponding SingleSignOnEntry
+ SingleSignOnEntry sso = null;
synchronized (cache) {
- cache.put(cookie, new SingleSignOnEntry(principal, authType));
+ sso = (SingleSignOnEntry) cache.remove(ssoId);
}
+ if (sso == null)
+ return;
+
+ // Expire any associated sessions
+ Session sessions[] = sso.findSessions();
+ for (int i = 0; i < sessions.length; i++) {
+ if (debug >= 2)
+ log(" Invalidating session " + sessions[i]);
+ // Remove from reverse cache first to avoid recursion
+ synchronized (reverse) {
+ reverse.remove(sessions[i]);
+ }
+ // Invalidate this session
+ sessions[i].expire();
+ }
+ // NOTE: Clients may still possess the old single sign on cookie,
+ // but it will be removed on the next request since it is no longer
+ // in the cache
+
}
/**
- * Return a String rendering of this object.
+ * Register the specified Principal as being associated with the specified
+ * value for the single sign on identifier.
+ *
+ * @param ssoId Single sign on identifier to register
+ * @param principal Associated user principal that is identified
+ * @param authType Authentication type used to authenticate this
+ * user principal
*/
- public String toString() {
+ void register(String ssoId, Principal principal, String authType) {
- StringBuffer sb = new StringBuffer("SingleSignOn[");
- sb.append(container.getName());
- sb.append("]");
- return (sb.toString());
+ if (debug >= 1)
+ log("Registering sso id '" + ssoId + "' for user '" +
+ principal.getName() + "' with auth type '" + authType + "'");
+ synchronized (cache) {
+ cache.put(ssoId, new SingleSignOnEntry(principal, authType));
+ }
+
}
@@ -345,16 +535,15 @@
/**
- * Look up and return the cached Principal associated with this cookie
- * value, if there is one; otherwise return <code>null</code>.
+ * Look up and return the cached SingleSignOn entry associated with this
+ * sso id value, if there is one; otherwise return <code>null</code>.
*
- * @param cookie Cookie value to look up
+ * @param ssoId Single sign on identifier to look up
*/
- protected SingleSignOnEntry lookup(String cookie) {
+ protected SingleSignOnEntry lookup(String ssoId) {
- // FIXME - No timeout checking on cached Principals
synchronized (cache) {
- return ((SingleSignOnEntry) cache.get(cookie));
+ return ((SingleSignOnEntry) cache.get(ssoId));
}
}
@@ -371,14 +560,32 @@
*/
class SingleSignOnEntry {
+ public String authType = null;
+
public Principal principal = null;
- public String authType = null;
+ public Session sessions[] = new Session[0];
public SingleSignOnEntry(Principal principal, String authType) {
super();
this.principal = principal;
this.authType = authType;
+ }
+
+ public synchronized void addSession(SingleSignOn sso, Session session) {
+ for (int i = 0; i < sessions.length; i++) {
+ if (session == sessions[i])
+ return;
+ }
+ Session results[] = new Session[sessions.length + 1];
+ System.arraycopy(sessions, 0, results, 0, sessions.length);
+ results[sessions.length] = session;
+ sessions = results;
+ session.addSessionListener(sso);
+ }
+
+ public synchronized Session[] findSessions() {
+ return (this.sessions);
}
}
1.28 +33 -4
jakarta-tomcat-4.0/catalina/src/share/org/apache/catalina/connector/HttpRequestBase.java
Index: HttpRequestBase.java
===================================================================
RCS file:
/home/cvs/jakarta-tomcat-4.0/catalina/src/share/org/apache/catalina/connector/HttpRequestBase.java,v
retrieving revision 1.27
retrieving revision 1.28
diff -u -r1.27 -r1.28
--- HttpRequestBase.java 2001/07/22 20:25:06 1.27
+++ HttpRequestBase.java 2001/07/29 03:43:54 1.28
@@ -1,7 +1,7 @@
/*
- * $Header:
/home/cvs/jakarta-tomcat-4.0/catalina/src/share/org/apache/catalina/connector/HttpRequestBase.java,v
1.27 2001/07/22 20:25:06 pier Exp $
- * $Revision: 1.27 $
- * $Date: 2001/07/22 20:25:06 $
+ * $Header:
/home/cvs/jakarta-tomcat-4.0/catalina/src/share/org/apache/catalina/connector/HttpRequestBase.java,v
1.28 2001/07/29 03:43:54 craigmcc Exp $
+ * $Revision: 1.28 $
+ * $Date: 2001/07/29 03:43:54 $
*
* ====================================================================
*
@@ -101,7 +101,7 @@
* be implemented.
*
* @author Craig R. McClanahan
- * @version $Revision: 1.27 $ $Date: 2001/07/22 20:25:06 $
+ * @version $Revision: 1.28 $ $Date: 2001/07/29 03:43:54 $
*/
public class HttpRequestBase
@@ -265,6 +265,12 @@
/**
+ * The single sign on identifier with which this request is associated.
+ */
+ protected String ssoId = null;
+
+
+ /**
* The Principal who has been authenticated for this Request.
*/
protected Principal userPrincipal = null;
@@ -296,6 +302,28 @@
}
+ /**
+ * Return the single sign on identifier this request is associated with.
+ */
+ public String getSsoId() {
+
+ return (ssoId);
+
+ }
+
+
+ /**
+ * Set the single sign on identifier this request is associated with.
+ *
+ * @param ssoId The new SSO identifier (if any)
+ */
+ public void setSsoId(String ssoId) {
+
+ this.ssoId = ssoId;
+
+ }
+
+
// --------------------------------------------------------- Public Methods
@@ -424,6 +452,7 @@
secure = false;
servletPath = null;
session = null;
+ ssoId = null;
userPrincipal = null;
}
1.14 +36 -5
jakarta-tomcat-4.0/catalina/src/share/org/apache/catalina/core/ContainerBase.java
Index: ContainerBase.java
===================================================================
RCS file:
/home/cvs/jakarta-tomcat-4.0/catalina/src/share/org/apache/catalina/core/ContainerBase.java,v
retrieving revision 1.13
retrieving revision 1.14
diff -u -r1.13 -r1.14
--- ContainerBase.java 2001/07/22 20:25:08 1.13
+++ ContainerBase.java 2001/07/29 03:43:54 1.14
@@ -1,7 +1,7 @@
/*
- * $Header:
/home/cvs/jakarta-tomcat-4.0/catalina/src/share/org/apache/catalina/core/ContainerBase.java,v
1.13 2001/07/22 20:25:08 pier Exp $
- * $Revision: 1.13 $
- * $Date: 2001/07/22 20:25:08 $
+ * $Header:
/home/cvs/jakarta-tomcat-4.0/catalina/src/share/org/apache/catalina/core/ContainerBase.java,v
1.14 2001/07/29 03:43:54 craigmcc Exp $
+ * $Revision: 1.14 $
+ * $Date: 2001/07/29 03:43:54 $
*
* ====================================================================
*
@@ -154,11 +154,11 @@
* class comments of the implementation class.
*
* @author Craig R. McClanahan
- * @version $Revision: 1.13 $ $Date: 2001/07/22 20:25:08 $
+ * @version $Revision: 1.14 $ $Date: 2001/07/29 03:43:54 $
*/
public abstract class ContainerBase
- implements Container, Lifecycle {
+ implements Container, Lifecycle, Pipeline {
// ----------------------------------------------------- Instance Variables
@@ -1223,6 +1223,17 @@
/**
+ * <p>Return the Valve instance that has been distinguished as the basic
+ * Valve for this Pipeline (if any).
+ */
+ public Valve getBasic() {
+
+ return (pipeline.getBasic());
+
+ }
+
+
+ /**
* Return the set of Valves in the pipeline associated with this
* Container, including the basic Valve (if any). If there are no
* such Valves, a zero-length array is returned.
@@ -1246,6 +1257,26 @@
fireContainerEvent(REMOVE_VALVE_EVENT, valve);
}
+
+
+ /**
+ * <p>Set the Valve instance that has been distinguished as the basic
+ * Valve for this Pipeline (if any). Prioer to setting the basic Valve,
+ * the Valve's <code>setContainer()</code> will be called, if it
+ * implements <code>Contained</code>, with the owning Container as an
+ * argument. The method may throw an <code>IllegalArgumentException</code>
+ * if this Valve chooses not to be associated with this Container, or
+ * <code>IllegalStateException</code> if it is already associated with
+ * a different Container.</p>
+ *
+ * @param valve Valve to be distinguished as the basic Valve
+ */
+ public void setBasic(Valve valve) {
+
+ pipeline.setBasic(valve);
+
+ }
+
// ------------------------------------------------------ Protected Methods
1.24 +65 -4
jakarta-tomcat-4.0/catalina/src/share/org/apache/catalina/session/StandardSession.java
Index: StandardSession.java
===================================================================
RCS file:
/home/cvs/jakarta-tomcat-4.0/catalina/src/share/org/apache/catalina/session/StandardSession.java,v
retrieving revision 1.23
retrieving revision 1.24
diff -u -r1.23 -r1.24
--- StandardSession.java 2001/07/22 20:25:12 1.23
+++ StandardSession.java 2001/07/29 03:43:54 1.24
@@ -1,7 +1,7 @@
/*
- * $Header:
/home/cvs/jakarta-tomcat-4.0/catalina/src/share/org/apache/catalina/session/StandardSession.java,v
1.23 2001/07/22 20:25:12 pier Exp $
- * $Revision: 1.23 $
- * $Date: 2001/07/22 20:25:12 $
+ * $Header:
/home/cvs/jakarta-tomcat-4.0/catalina/src/share/org/apache/catalina/session/StandardSession.java,v
1.24 2001/07/29 03:43:54 craigmcc Exp $
+ * $Revision: 1.24 $
+ * $Date: 2001/07/29 03:43:54 $
*
* ====================================================================
*
@@ -88,6 +88,8 @@
import org.apache.catalina.Context;
import org.apache.catalina.Manager;
import org.apache.catalina.Session;
+import org.apache.catalina.SessionEvent;
+import org.apache.catalina.SessionListener;
import org.apache.catalina.core.StandardContext;
import org.apache.catalina.util.Enumerator;
import org.apache.catalina.util.StringManager;
@@ -111,7 +113,7 @@
* @author Craig R. McClanahan
* @author Sean Legassick
* @author <a href="mailto:[EMAIL PROTECTED]">Jon S. Stevens</a>
- * @version $Revision: 1.23 $ $Date: 2001/07/22 20:25:12 $
+ * @version $Revision: 1.24 $ $Date: 2001/07/29 03:43:54 $
*/
class StandardSession
@@ -209,6 +211,12 @@
/**
+ * The session event listeners for this Session.
+ */
+ private transient ArrayList listeners = new ArrayList();
+
+
+ /**
* The Manager with which this Session is associated.
*/
private Manager manager = null;
@@ -328,6 +336,9 @@
if (manager != null)
manager.add(this);
+ // Notify interested session event listeners
+ fireSessionEvent(Session.SESSION_CREATED_EVENT, null);
+
// Notify interested application event listeners
StandardContext context = (StandardContext) manager.getContainer();
Object listeners[] = context.getApplicationListeners();
@@ -530,6 +541,18 @@
/**
+ * Add a session event listener to this component.
+ */
+ public void addSessionListener(SessionListener listener) {
+
+ synchronized (listeners) {
+ listeners.add(listener);
+ }
+
+ }
+
+
+ /**
* Perform the internal processing required to invalidate this session,
* without triggering an exception if the session has already expired.
*/
@@ -550,6 +573,9 @@
for (int i = 0; i < keys.length; i++)
removeAttribute(keys[i]);
+ // Notify interested session event listeners
+ fireSessionEvent(Session.SESSION_DESTROYED_EVENT, null);
+
// Notify interested application event listeners
// FIXME - Assumes we call listeners in reverse order
StandardContext context = (StandardContext) manager.getContainer();
@@ -658,6 +684,18 @@
/**
+ * Remove a session event listener from this component.
+ */
+ public void removeSessionListener(SessionListener listener) {
+
+ synchronized (listeners) {
+ listeners.remove(listener);
+ }
+
+ }
+
+
+ /**
* Return a string representation of this object.
*/
public String toString() {
@@ -1242,6 +1280,29 @@
// -------------------------------------------------------- Private Methods
+
+
+ /**
+ * Notify all session event listeners that a particular event has
+ * occurred for this Session. The default implementation performs
+ * this notification synchronously using the calling thread.
+ *
+ * @param type Event type
+ * @param data Event data
+ */
+ public void fireSessionEvent(String type, Object data) {
+
+ if (listeners.size() < 1)
+ return;
+ SessionEvent event = new SessionEvent(this, type, data);
+ SessionListener list[] = new SessionListener[0];
+ synchronized (listeners) {
+ list = (SessionListener[]) listeners.toArray(list);
+ }
+ for (int i = 0; i < list.length; i++)
+ ((SessionListener) list[i]).sessionEvent(event);
+
+ }
/**