You are viewing a plain text version of this content. The canonical link for it is here.
Posted to dev@tomcat.apache.org by ma...@apache.org on 2003/12/24 21:40:50 UTC
cvs commit: jakarta-tomcat-4.0/webapps/tomcat-docs/config valve.xml
markt 2003/12/24 12:40:50
Modified: catalina/src/share/org/apache/catalina/authenticator
AuthenticatorBase.java BasicAuthenticator.java
DigestAuthenticator.java FormAuthenticator.java
NonLoginAuthenticator.java SSLAuthenticator.java
SingleSignOn.java
webapps/tomcat-docs/config valve.xml
Log:
- Port of patch from TC5.
- Fix bugs 4350, 9077, 10040 and 23881.
- SSO in embedded Tomcat.
- Patch provided by Brian Stansberry.
Revision Changes Path
1.39 +87 -24 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.38
retrieving revision 1.39
diff -u -r1.38 -r1.39
--- AuthenticatorBase.java 18 Jul 2003 04:39:31 -0000 1.38
+++ AuthenticatorBase.java 24 Dec 2003 20:40:50 -0000 1.39
@@ -84,7 +84,6 @@
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;
@@ -99,7 +98,6 @@
import org.apache.catalina.deploy.LoginConfig;
import org.apache.catalina.deploy.SecurityConstraint;
import org.apache.catalina.util.LifecycleSupport;
-import org.apache.catalina.util.RequestUtil;
import org.apache.catalina.util.StringManager;
import org.apache.catalina.valves.ValveBase;
@@ -666,7 +664,7 @@
*
* @param request Request we are processing
* @param response Response we are creating
- * @param login Login configuration describing how authentication
+ * @param config Login configuration describing how authentication
* should be performed
*
* @exception IOException if an input/output error occurs
@@ -817,7 +815,6 @@
protected synchronized String generateSessionId() {
// Generate a byte array containing a session identifier
- Random random = getRandom();
byte bytes[] = new byte[SESSION_ID_BYTES];
getRandom().nextBytes(bytes);
bytes = getDigest().digest(bytes);
@@ -975,6 +972,52 @@
/**
+ * Attempts reauthentication to the <code>Realm</code> using
+ * the credentials included in argument <code>entry</code>.
+ *
+ * @param ssoId identifier of SingleSignOn session with which the
+ * caller is associated
+ * @param request the request that needs to be authenticated
+ */
+ protected boolean reauthenticateFromSSO(String ssoId, HttpRequest request) {
+
+ if (sso == null || ssoId == null)
+ return false;
+
+ boolean reauthenticated = false;
+
+ SingleSignOnEntry entry = sso.lookup(ssoId);
+ if (entry != null && entry.getCanReauthenticate()) {
+ Principal reauthPrincipal = null;
+ Container parent = getContainer();
+ if (parent != null) {
+ Realm realm = getContainer().getRealm();
+ String username = entry.getUsername();
+ if (realm != null && username != null) {
+ reauthPrincipal =
+ realm.authenticate(username, entry.getPassword());
+ }
+ }
+
+ if (reauthPrincipal != null) {
+ associate(ssoId, getSession(request, true));
+ request.setAuthType(entry.getAuthType());
+ request.setUserPrincipal(reauthPrincipal);
+
+ reauthenticated = true;
+ if (debug >= 1) {
+ log(" Reauthenticated cached principal '" +
+ entry.getPrincipal().getName() + "' with auth type '" +
+ entry.getAuthType() + "'");
+ }
+ }
+ }
+
+ return reauthenticated;
+ }
+
+
+ /**
* Register an authenticated Principal and authentication type in our
* request, in the current session (if there is one), and with our
* SingleSignOn valve, if there is one. Set the appropriate cookie
@@ -998,10 +1041,10 @@
// Cache the authentication information in our request
request.setAuthType(authType);
request.setUserPrincipal(principal);
-
+
+ Session session = getSession(request, false);
// Cache the authentication information in our session, if any
- if (cache) {
- Session session = getSession(request, false);
+ if (cache) {
if (session != null) {
session.setAuthType(authType);
session.setPrincipal(principal);
@@ -1019,19 +1062,39 @@
// Construct a cookie to be returned to the client
if (sso == null)
return;
- HttpServletRequest hreq =
- (HttpServletRequest) request.getRequest();
- HttpServletResponse hres =
- (HttpServletResponse) response.getResponse();
- String value = generateSessionId();
- Cookie cookie = new Cookie(Constants.SINGLE_SIGN_ON_COOKIE, value);
- cookie.setMaxAge(-1);
- cookie.setPath("/");
- hres.addCookie(cookie);
-
- // Register this principal with our SSO valve
- sso.register(value, principal, authType, username, password);
- request.setNote(Constants.REQ_SSOID_NOTE, value);
+
+ // Only create a new SSO entry if the SSO did not already set a note
+ // for an existing entry (as it would do with subsequent requests
+ // for DIGEST and SSL authenticated contexts)
+ String ssoId = (String) request.getNote(Constants.REQ_SSOID_NOTE);
+ if (ssoId == null) {
+ // Construct a cookie to be returned to the client
+ HttpServletResponse hres =
+ (HttpServletResponse) response.getResponse();
+ ssoId = generateSessionId();
+ Cookie cookie = new Cookie(Constants.SINGLE_SIGN_ON_COOKIE, ssoId);
+ cookie.setMaxAge(-1);
+ cookie.setPath("/");
+ hres.addCookie(cookie);
+
+ // Register this principal with our SSO valve
+ sso.register(ssoId, principal, authType, username, password);
+ request.setNote(Constants.REQ_SSOID_NOTE, ssoId);
+
+ } else {
+ // Update the SSO session with the latest authentication data
+ sso.update(ssoId, principal, authType, username, password);
+ }
+
+ // Fix for Bug 10040
+ // Always associate a session with a new SSO reqistration.
+ // SSO entries are only removed from the SSO registry map when
+ // associated sessions are destroyed; if a new SSO entry is created
+ // above for this request and the user never revisits the context, the
+ // SSO entry will never be cleared if we don't associate the session
+ if (session == null)
+ session = getSession(request, true);
+ sso.associate(ssoId, session);
}
1.13 +23 -5 jakarta-tomcat-4.0/catalina/src/share/org/apache/catalina/authenticator/BasicAuthenticator.java
Index: BasicAuthenticator.java
===================================================================
RCS file: /home/cvs/jakarta-tomcat-4.0/catalina/src/share/org/apache/catalina/authenticator/BasicAuthenticator.java,v
retrieving revision 1.12
retrieving revision 1.13
diff -u -r1.12 -r1.13
--- BasicAuthenticator.java 23 Mar 2002 17:52:16 -0000 1.12
+++ BasicAuthenticator.java 24 Dec 2003 20:40:50 -0000 1.13
@@ -131,7 +131,7 @@
*
* @param request Request we are processing
* @param response Response we are creating
- * @param login Login configuration describing how authentication
+ * @param config Login configuration describing how authentication
* should be performed
*
* @exception IOException if an input/output error occurs
@@ -144,10 +144,28 @@
// Have we already authenticated someone?
Principal principal =
((HttpServletRequest) request.getRequest()).getUserPrincipal();
+ String ssoId = (String) request.getNote(Constants.REQ_SSOID_NOTE);
if (principal != null) {
if (debug >= 1)
log("Already authenticated '" + principal.getName() + "'");
+ // Associate the session with any existing SSO session
+ if (ssoId != null)
+ associate(ssoId, getSession(request, true));
return (true);
+ }
+
+ // Is there an SSO session against which we can try to reauthenticate?
+ if (ssoId != null) {
+ if (debug >= 1)
+ log("SSO Id " + ssoId + " set; attempting reauthentication");
+ /* Try to reauthenticate using data cached by SSO. If this fails,
+ either the original SSO logon was of DIGEST or SSL (which
+ we can't reauthenticate ourselves because there is no
+ cached username and password), or the realm denied
+ the user's reauthentication for some reason.
+ In either case we have to prompt the user for a logon */
+ if (reauthenticateFromSSO(ssoId, request))
+ return true;
}
// Validate any credentials already included with this request
1.12 +41 -12 jakarta-tomcat-4.0/catalina/src/share/org/apache/catalina/authenticator/DigestAuthenticator.java
Index: DigestAuthenticator.java
===================================================================
RCS file: /home/cvs/jakarta-tomcat-4.0/catalina/src/share/org/apache/catalina/authenticator/DigestAuthenticator.java,v
retrieving revision 1.11
retrieving revision 1.12
diff -u -r1.11 -r1.12
--- DigestAuthenticator.java 24 Mar 2003 23:19:19 -0000 1.11
+++ DigestAuthenticator.java 24 Dec 2003 20:40:50 -0000 1.12
@@ -76,7 +76,6 @@
import org.apache.catalina.HttpRequest;
import org.apache.catalina.HttpResponse;
import org.apache.catalina.Realm;
-import org.apache.catalina.Session;
import org.apache.catalina.deploy.LoginConfig;
import org.apache.catalina.util.MD5Encoder;
@@ -205,7 +204,7 @@
*
* @param request Request we are processing
* @param response Response we are creating
- * @param login Login configuration describing how authentication
+ * @param config Login configuration describing how authentication
* should be performed
*
* @exception IOException if an input/output error occurs
@@ -218,8 +217,41 @@
// Have we already authenticated someone?
Principal principal =
((HttpServletRequest) request.getRequest()).getUserPrincipal();
- if (principal != null)
+ //String ssoId = (String) request.getNote(Constants.REQ_SSOID_NOTE);
+ if (principal != null) {
+ if (debug >= 1)
+ log("Already authenticated '" + principal.getName() + "'");
+ // Associate the session with any existing SSO session in order
+ // to get coordinated session invalidation at logout
+ String ssoId = (String) request.getNote(Constants.REQ_SSOID_NOTE);
+ if (ssoId != null)
+ associate(ssoId, getSession(request, true));
return (true);
+ }
+
+ // NOTE: We don't try to reauthenticate using any existing SSO session,
+ // because that will only work if the original authentication was
+ // BASIC or FORM, which are less secure than the DIGEST auth-type
+ // specified for this webapp
+ //
+ // Uncomment below to allow previous FORM or BASIC authentications
+ // to authenticate users for this webapp
+ // TODO make this a configurable attribute (in SingleSignOn??)
+ /*
+ // Is there an SSO session against which we can try to reauthenticate?
+ if (ssoId != null) {
+ if (debug >= 1)
+ log("SSO Id " + ssoId + " set; attempting reauthentication");
+ // Try to reauthenticate using data cached by SSO. If this fails,
+ // either the original SSO logon was of DIGEST or SSL (which
+ // we can't reauthenticate ourselves because there is no
+ // cached username and password), or the realm denied
+ // the user's reauthentication for some reason.
+ // In either case we get logon credentials from the user.
+ if (reauthenticateFromSSO(ssoId, request))
+ return true;
+ }
+ */
// Validate any credentials already included with this request
HttpServletRequest hreq =
@@ -263,8 +295,6 @@
*
* @param request HTTP servlet request
* @param authorization Authorization credentials from this request
- * @param login Login configuration describing how authentication
- * should be performed
* @param realm Realm used to authenticate Principals
*/
protected static Principal findPrincipal(HttpServletRequest request,
@@ -291,7 +321,6 @@
String qop = null;
String uri = null;
String response = null;
- String opaque = null;
String method = request.getMethod();
while (commaTokenizer.hasMoreTokens()) {
@@ -442,8 +471,8 @@
* </pre>
*
* @param request HTTP Servlet request
- * @param resonse HTTP Servlet response
- * @param login Login configuration describing how authentication
+ * @param response HTTP Servlet response
+ * @param config Login configuration describing how authentication
* should be performed
* @param nOnce nonce token
*/
1.21 +22 -11 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.20
retrieving revision 1.21
diff -u -r1.20 -r1.21
--- FormAuthenticator.java 14 Mar 2002 20:58:24 -0000 1.20
+++ FormAuthenticator.java 24 Dec 2003 20:40:50 -0000 1.21
@@ -74,7 +74,6 @@
import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
-import javax.servlet.http.HttpSession;
import org.apache.catalina.HttpRequest;
import org.apache.catalina.HttpResponse;
import org.apache.catalina.Realm;
@@ -129,7 +128,7 @@
*
* @param request Request we are processing
* @param response Response we are creating
- * @param login Login configuration describing how authentication
+ * @param config Login configuration describing how authentication
* should be performed
*
* @exception IOException if an input/output error occurs
@@ -148,16 +147,31 @@
// Have we already authenticated someone?
Principal principal = hreq.getUserPrincipal();
+ String ssoId = (String) request.getNote(Constants.REQ_SSOID_NOTE);
if (principal != null) {
if (debug >= 1)
log("Already authenticated '" +
principal.getName() + "'");
- String ssoId = (String) request.getNote(Constants.REQ_SSOID_NOTE);
+ // Associate the session with any existing SSO session
if (ssoId != null)
associate(ssoId, getSession(request, true));
return (true);
}
+ // Is there an SSO session against which we can try to reauthenticate?
+ if (ssoId != null) {
+ if (debug >= 1)
+ log("SSO Id " + ssoId + " set; attempting reauthentication");
+ // Try to reauthenticate using data cached by SSO. If this fails,
+ // either the original SSO logon was of DIGEST or SSL (which
+ // we can't reauthenticate ourselves because there is no
+ // cached username and password), or the realm denied
+ // the user's reauthentication for some reason.
+ // In either case we have to prompt the user for a logon */
+ if (reauthenticateFromSSO(ssoId, request))
+ return true;
+ }
+
// Have we authenticated this user before but have caching disabled?
if (!cache) {
session = getSession(request, true);
@@ -195,9 +209,6 @@
register(request, response, principal, Constants.FORM_METHOD,
(String) session.getNote(Constants.SESS_USERNAME_NOTE),
(String) session.getNote(Constants.SESS_PASSWORD_NOTE));
- String ssoId = (String) request.getNote(Constants.REQ_SSOID_NOTE);
- if (ssoId != null)
- associate(ssoId, session);
if (restoreRequest(request, session)) {
if (debug >= 1)
log("Proceed to restored request");
@@ -377,7 +388,7 @@
while (paramNames.hasNext()) {
String paramName = (String) paramNames.next();
String paramValues[] =
- (String[]) saved.getParameterValues(paramName);
+ saved.getParameterValues(paramName);
request.addParameter(paramName, paramValues);
}
}
1.4 +15 -10 jakarta-tomcat-4.0/catalina/src/share/org/apache/catalina/authenticator/NonLoginAuthenticator.java
Index: NonLoginAuthenticator.java
===================================================================
RCS file: /home/cvs/jakarta-tomcat-4.0/catalina/src/share/org/apache/catalina/authenticator/NonLoginAuthenticator.java,v
retrieving revision 1.3
retrieving revision 1.4
diff -u -r1.3 -r1.4
--- NonLoginAuthenticator.java 22 Jul 2001 20:09:19 -0000 1.3
+++ NonLoginAuthenticator.java 24 Dec 2003 20:40:50 -0000 1.4
@@ -66,13 +66,9 @@
import java.io.IOException;
-import java.security.Principal;
-import javax.servlet.http.HttpServletRequest;
-import javax.servlet.http.HttpServletResponse;
+
import org.apache.catalina.HttpRequest;
import org.apache.catalina.HttpResponse;
-import org.apache.catalina.Realm;
-import org.apache.catalina.Session;
import org.apache.catalina.deploy.LoginConfig;
@@ -123,7 +119,7 @@
*
* @param request Request we are processing
* @param response Response we are creating
- * @param login Login configuration describing how authentication
+ * @param config Login configuration describing how authentication
* should be performed
*
* @exception IOException if an input/output error occurs
@@ -132,6 +128,15 @@
HttpResponse response,
LoginConfig config)
throws IOException {
+
+ /* Associating this request's session with an SSO would allow
+ coordinated session invalidation, but should the session for
+ a webapp that the user didn't log into be invalidated when
+ another session is logged out?
+ String ssoId = (String) request.getNote(Constants.REQ_SSOID_NOTE);
+ if (ssoId != null)
+ associate(ssoId, getSession(request, true));
+ */
if (debug >= 1)
log("User authentication is not required");
1.14 +35 -8 jakarta-tomcat-4.0/catalina/src/share/org/apache/catalina/authenticator/SSLAuthenticator.java
Index: SSLAuthenticator.java
===================================================================
RCS file: /home/cvs/jakarta-tomcat-4.0/catalina/src/share/org/apache/catalina/authenticator/SSLAuthenticator.java,v
retrieving revision 1.13
retrieving revision 1.14
diff -u -r1.13 -r1.14
--- SSLAuthenticator.java 23 Sep 2002 00:25:10 -0000 1.13
+++ SSLAuthenticator.java 24 Dec 2003 20:40:50 -0000 1.14
@@ -73,10 +73,7 @@
import org.apache.catalina.Globals;
import org.apache.catalina.HttpRequest;
import org.apache.catalina.HttpResponse;
-import org.apache.catalina.Lifecycle;
import org.apache.catalina.LifecycleException;
-import org.apache.catalina.Realm;
-import org.apache.catalina.Session;
import org.apache.catalina.deploy.LoginConfig;
@@ -124,7 +121,7 @@
*
* @param request Request we are processing
* @param response Response we are creating
- * @param login Login configuration describing how authentication
+ * @param config Login configuration describing how authentication
* should be performed
*
* @exception IOException if an input/output error occurs
@@ -137,11 +134,41 @@
// Have we already authenticated someone?
Principal principal =
((HttpServletRequest) request.getRequest()).getUserPrincipal();
+ //String ssoId = (String) request.getNote(Constants.REQ_SSOID_NOTE);
if (principal != null) {
if (debug >= 1)
log("Already authenticated '" + principal.getName() + "'");
+ // Associate the session with any existing SSO session in order
+ // to get coordinated session invalidation at logout
+ String ssoId = (String) request.getNote(Constants.REQ_SSOID_NOTE);
+ if (ssoId != null)
+ associate(ssoId, getSession(request, true));
return (true);
}
+
+ // NOTE: We don't try to reauthenticate using any existing SSO session,
+ // because that will only work if the original authentication was
+ // BASIC or FORM, which are less secure than the CLIENT-CERT auth-type
+ // specified for this webapp
+ //
+ // Uncomment below to allow previous FORM or BASIC authentications
+ // to authenticate users for this webapp
+ // TODO make this a configurable attribute (in SingleSignOn??)
+ /*
+ // Is there an SSO session against which we can try to reauthenticate?
+ if (ssoId != null) {
+ if (debug >= 1)
+ log("SSO Id " + ssoId + " set; attempting reauthentication");
+ // Try to reauthenticate using data cached by SSO. If this fails,
+ // either the original SSO logon was of DIGEST or SSL (which
+ // we can't reauthenticate ourselves because there is no
+ // cached username and password), or the realm denied
+ // the user's reauthentication for some reason.
+ // In either case we have to prompt the user for a logon
+ if (reauthenticateFromSSO(ssoId, request))
+ return true;
+ }
+ */
// Retrieve the certificate chain for this client
HttpServletResponse hres =
1.13 +179 -57 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.12
retrieving revision 1.13
diff -u -r1.12 -r1.13
--- SingleSignOn.java 23 Dec 2003 17:55:39 -0000 1.12
+++ SingleSignOn.java 24 Dec 2003 20:40:50 -0000 1.13
@@ -145,6 +145,14 @@
*/
protected LifecycleSupport lifecycle = new LifecycleSupport(this);
+
+ /**
+ * Indicates whether this valve should require a downstream Authenticator to
+ * reauthenticate each request, or if it itself can bind a UserPrincipal
+ * and AuthType object to the request.
+ */
+ private boolean requireReauthentication = false;
+
/**
* The cache of single sign on identifiers, keyed by the Session that is
@@ -191,6 +199,75 @@
}
+ /**
+ * Gets whether each request needs to be reauthenticated (by an
+ * Authenticator downstream in the pipeline) to the security
+ * <code>Realm</code>, or if this Valve can itself bind security info
+ * to the request based on the presence of a valid SSO entry without
+ * rechecking with the <code>Realm</code..
+ *
+ * @return <code>true</code> if it is required that a downstream
+ * Authenticator reauthenticate each request before calls to
+ * <code>HttpServletRequest.setUserPrincipal()</code>
+ * and <code>HttpServletRequest.setAuthType()</code> are made;
+ * <code>false</code> if the <code>Valve</code> can itself make
+ * those calls relying on the presence of a valid SingleSignOn
+ * entry associated with the request.
+ *
+ * @see #setRequireReauthentication
+ */
+ public boolean getRequireReauthentication()
+ {
+ return requireReauthentication;
+ }
+
+
+ /**
+ * Sets whether each request needs to be reauthenticated (by an
+ * Authenticator downstream in the pipeline) to the security
+ * <code>Realm</code>, or if this Valve can itself bind security info
+ * to the request, based on the presence of a valid SSO entry, without
+ * rechecking with the <code>Realm</code.
+ * <p>
+ * If this property is <code>false</code> (the default), this
+ * <code>Valve</code> will bind a UserPrincipal and AuthType to the request
+ * if a valid SSO entry is associated with the request. It will not notify
+ * the security <code>Realm</code> of the incoming request.
+ * <p>
+ * This property should be set to <code>true</code> if the overall server
+ * configuration requires that the <code>Realm</code> reauthenticate each
+ * request thread. An example of such a configuration would be one where
+ * the <code>Realm</code> implementation provides security for both a
+ * web tier and an associated EJB tier, and needs to set security
+ * credentials on each request thread in order to support EJB access.
+ * <p>
+ * If this property is set to <code>true</code>, this Valve will set flags
+ * on the request notifying the downstream Authenticator that the request
+ * is associated with an SSO session. The Authenticator will then call its
+ * {@link AuthenticatorBase#reauthenticateFromSSO reauthenticateFromSSO}
+ * method to attempt to reauthenticate the request to the
+ * <code>Realm</code>, using any credentials that were cached with this
+ * Valve.
+ * <p>
+ * The default value of this property is <code>false</code>, in order
+ * to maintain backward compatibility with previous versions of Tomcat.
+ *
+ * @param required <code>true</code> if it is required that a downstream
+ * Authenticator reauthenticate each request before calls
+ * to <code>HttpServletRequest.setUserPrincipal()</code>
+ * and <code>HttpServletRequest.setAuthType()</code> are
+ * made; <code>false</code> if the <code>Valve</code> can
+ * itself make those calls relying on the presence of a
+ * valid SingleSignOn entry associated with the request.
+ *
+ * @see AuthenticatorBase#reauthenticateFromSSO
+ */
+ public void setRequireReauthentication(boolean required)
+ {
+ this.requireReauthentication = required;
+ }
+
+
// ------------------------------------------------------ Lifecycle Methods
@@ -299,9 +376,23 @@
}
if (ssoId == null)
return;
+
- // Deregister this single session id, invalidating associated sessions
- deregister(ssoId);
+ /*
+ * Was the session destroyed as the result of a timeout?
+ * If so, we'll just remove the expired session from the
+ * SSO. If the session was logged out, we'll log out
+ * of all session associated with the SSO.
+ */
+ if (System.currentTimeMillis() - session.getLastAccessedTime() >=
+ session.getMaxInactiveInterval() * 1000) {
+ removeSession(ssoId, session);
+ }
+ else {
+ // The session was logged out.
+ // Deregister this single session id, invalidating associated sessions
+ deregister(ssoId);
+ }
}
@@ -384,11 +475,14 @@
if (entry != null) {
if (debug >= 1)
log(" Found cached principal '" +
- entry.principal.getName() + "' with auth type '" +
- entry.authType + "'");
+ entry.getPrincipal().getName() + "' with auth type '" +
+ entry.getAuthType() + "'");
request.setNote(Constants.REQ_SSOID_NOTE, cookie.getValue());
- ((HttpRequest) request).setAuthType(entry.authType);
- ((HttpRequest) request).setUserPrincipal(entry.principal);
+ // Only set security elements if reauthentication is not required
+ if (!getRequireReauthentication()) {
+ ((HttpRequest) request).setAuthType(entry.getAuthType());
+ ((HttpRequest) request).setUserPrincipal(entry.getPrincipal());
+ }
} else {
if (debug >= 1)
log(" No cached principal found, erasing SSO cookie");
@@ -510,6 +604,81 @@
}
+
+ /**
+ * Remove a single Session from a SingleSignOn. Called when
+ * a session is timed out and no longer active.
+ *
+ * @param ssoId Single sign on identifier from which to remove the session.
+ * @param session the session to be removed.
+ */
+ void removeSession(String ssoId, Session session) {
+
+ if (debug >= 1)
+ log("Removing session " + session.toString() + " from sso id " +
+ ssoId );
+
+ // Get a reference to the SingleSignOn
+ SingleSignOnEntry entry = lookup(ssoId);
+ if (entry == null)
+ return;
+
+ // Remove the inactive session from SingleSignOnEntry
+ entry.removeSession(session);
+
+ // Remove the inactive session from the 'reverse' Map.
+ synchronized(reverse) {
+ reverse.remove(session);
+ }
+
+ // If there are not sessions left in the SingleSignOnEntry,
+ // deregister the entry.
+ if (entry.findSessions().length == 0) {
+ deregister(ssoId);
+ }
+ }
+
+
+ /**
+ * Updates any <code>SingleSignOnEntry</code> found under key
+ * <code>ssoId</code> with the given authentication data.
+ * <p>
+ * The purpose of this method is to allow an SSO entry that was
+ * established without a username/password combination (i.e. established
+ * following DIGEST or CLIENT-CERT authentication) to be updated with
+ * a username and password if one becomes available through a subsequent
+ * BASIC or FORM authentication. The SSO entry will then be usable for
+ * reauthentication.
+ * <p>
+ * <b>NOTE:</b> Only updates the SSO entry if a call to
+ * <code>SingleSignOnEntry.getCanReauthenticate()</code> returns
+ * <code>false</code>; otherwise, it is assumed that the SSO entry already
+ * has sufficient information to allow reauthentication and that no update
+ * is needed.
+ *
+ * @param ssoId identifier of Single sign to be updated
+ * @param principal the <code>Principal</code> returned by the latest
+ * call to <code>Realm.authenticate</code>.
+ * @param authType the type of authenticator used (BASIC, CLIENT-CERT,
+ * DIGEST or FORM)
+ * @param username the username (if any) used for the authentication
+ * @param password the password (if any) used for the authentication
+ */
+ void update(String ssoId, Principal principal, String authType,
+ String username, String password) {
+
+ SingleSignOnEntry sso = lookup(ssoId);
+ if (sso != null && !sso.getCanReauthenticate()) {
+ if (debug >= 1)
+ log("Update sso id " + ssoId + " to auth type " + authType);
+
+ synchronized(sso) {
+ sso.updateCredentials(principal, authType, username, password);
+ }
+
+ }
+ }
+
// ------------------------------------------------------ Protected Methods
@@ -561,53 +730,6 @@
return ((SingleSignOnEntry) cache.get(ssoId));
}
- }
-
-
-}
-
-
-// ------------------------------------------------------------ Private Classes
-
-
-/**
- * A private class representing entries in the cache of authenticated users.
- */
-class SingleSignOnEntry {
-
- public String authType = null;
-
- public String password = null;
-
- public Principal principal = null;
-
- public Session sessions[] = new Session[0];
-
- public String username = null;
-
- public SingleSignOnEntry(Principal principal, String authType,
- String username, String password) {
- super();
- this.principal = principal;
- this.authType = authType;
- this.username = username;
- this.password = password;
- }
-
- 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.9 +10 -0 jakarta-tomcat-4.0/webapps/tomcat-docs/config/valve.xml
Index: valve.xml
===================================================================
RCS file: /home/cvs/jakarta-tomcat-4.0/webapps/tomcat-docs/config/valve.xml,v
retrieving revision 1.8
retrieving revision 1.9
diff -u -r1.8 -r1.9
--- valve.xml 12 Jan 2003 17:26:48 -0000 1.8
+++ valve.xml 24 Dec 2003 20:40:50 -0000 1.9
@@ -309,6 +309,16 @@
<p>Detail level of debugging messages created by this component. By
default, this is set to zero (0), which means no debug output.</p>
</attribute>
+
+ <attribute name="requireReauthentication" required="false">
+ <p>Default false. Flag to determine whether each request needs to be
+ reauthenticated to the security <strong>Realm</strong>. If "true", this
+ Valve uses cached security credentials (username and password) to
+ reauthenticate to the <strong>Realm</strong> each request associated
+ with an SSO session. If "false", the Valve can itself authenticate
+ requests based on the presence of a valid SSO cookie, without
+ rechecking with the <strong>Realm</strong>.</p>
+ </attribute>
</attributes>
---------------------------------------------------------------------
To unsubscribe, e-mail: tomcat-dev-unsubscribe@jakarta.apache.org
For additional commands, e-mail: tomcat-dev-help@jakarta.apache.org