Author: markt Date: Fri Dec 19 14:45:25 2014 New Revision: 1646744 URL: http://svn.apache.org/r1646744 Log: First pass at fixing https://issues.apache.org/bugzilla/show_bug.cgi?id=57338 so SSO entries are kept in sync across the cluster as nodes are added and removed.
Added: tomcat/tc8.0.x/trunk/java/org/apache/catalina/authenticator/SingleSignOnSessionKey.java (props changed) - copied unchanged from r1646104, tomcat/trunk/java/org/apache/catalina/authenticator/SingleSignOnSessionKey.java Removed: tomcat/tc8.0.x/trunk/java/org/apache/catalina/ha/authenticator/ClusterSingleSignOnListener.java tomcat/tc8.0.x/trunk/java/org/apache/catalina/ha/authenticator/SingleSignOnMessage.java Modified: tomcat/tc8.0.x/trunk/ (props changed) tomcat/tc8.0.x/trunk/java/org/apache/catalina/authenticator/LocalStrings.properties tomcat/tc8.0.x/trunk/java/org/apache/catalina/authenticator/SingleSignOn.java tomcat/tc8.0.x/trunk/java/org/apache/catalina/authenticator/SingleSignOnEntry.java tomcat/tc8.0.x/trunk/java/org/apache/catalina/ha/authenticator/ClusterSingleSignOn.java Propchange: tomcat/tc8.0.x/trunk/ ------------------------------------------------------------------------------ --- svn:mergeinfo (original) +++ svn:mergeinfo Fri Dec 19 14:45:25 2014 @@ -1 +1 @@ -/tomcat/trunk:1636524,1637156,1637176,1637188,1637331,1637684,1637695,1638720-1638725,1639653,1640010,1640083-1640084,1640088,1640275,1640322,1640347,1640361,1640365,1640403,1640410,1640652,1640655-1640658,1640688,1640700-1640883,1640903,1640976,1640978,1641000,1641026,1641038-1641039,1641051-1641052,1641058,1641064,1641300,1641369,1641374,1641380,1641486,1641634,1641656-1641692,1641704,1641707-1641718,1641720-1641722,1641735,1641981,1642233,1642280,1642554,1642564,1642595,1642606,1642668,1642679,1642697,1642699,1642766,1643002,1643045,1643054-1643055,1643066,1643121,1643128,1643206,1643209-1643210,1643216,1643249,1643270,1643283,1643309-1643310,1643323,1643365-1643366,1643370-1643371,1643465,1643474,1643536,1643570,1643634,1643649,1643651,1643654,1643675,1643731,1643733-1643734,1643761,1643766,1643814,1643937,1643963,1644017,1644169,1644201-1644203,1644321,1644323,1644516,1644523,1644529,1644535,1644730,1644768,1644784-1644785,1644790,1644793,1644815,1644884,1644886,1644890,1644892 ,1644910,1644924,1644929-1644930,1644935,1644989,1645011,1645247,1645355,1645357-1645358,1645455,1645465,1645469,1645471,1645473,1645475,1645486-1645488,1645626,1645641,1645685,1645743,1645763,1645951-1645953,1645955,1646098-1646102,1646302,1646304,1646420 +/tomcat/trunk:1636524,1637156,1637176,1637188,1637331,1637684,1637695,1638720-1638725,1639653,1640010,1640083-1640084,1640088,1640275,1640322,1640347,1640361,1640365,1640403,1640410,1640652,1640655-1640658,1640688,1640700-1640883,1640903,1640976,1640978,1641000,1641026,1641038-1641039,1641051-1641052,1641058,1641064,1641300,1641369,1641374,1641380,1641486,1641634,1641656-1641692,1641704,1641707-1641718,1641720-1641722,1641735,1641981,1642233,1642280,1642554,1642564,1642595,1642606,1642668,1642679,1642697,1642699,1642766,1643002,1643045,1643054-1643055,1643066,1643121,1643128,1643206,1643209-1643210,1643216,1643249,1643270,1643283,1643309-1643310,1643323,1643365-1643366,1643370-1643371,1643465,1643474,1643536,1643570,1643634,1643649,1643651,1643654,1643675,1643731,1643733-1643734,1643761,1643766,1643814,1643937,1643963,1644017,1644169,1644201-1644203,1644321,1644323,1644516,1644523,1644529,1644535,1644730,1644768,1644784-1644785,1644790,1644793,1644815,1644884,1644886,1644890,1644892 ,1644910,1644924,1644929-1644930,1644935,1644989,1645011,1645247,1645355,1645357-1645358,1645455,1645465,1645469,1645471,1645473,1645475,1645486-1645488,1645626,1645641,1645685,1645743,1645763,1645951-1645953,1645955,1646098-1646106,1646302,1646304,1646420 Modified: tomcat/tc8.0.x/trunk/java/org/apache/catalina/authenticator/LocalStrings.properties URL: http://svn.apache.org/viewvc/tomcat/tc8.0.x/trunk/java/org/apache/catalina/authenticator/LocalStrings.properties?rev=1646744&r1=1646743&r2=1646744&view=diff ============================================================================== --- tomcat/tc8.0.x/trunk/java/org/apache/catalina/authenticator/LocalStrings.properties (original) +++ tomcat/tc8.0.x/trunk/java/org/apache/catalina/authenticator/LocalStrings.properties Fri Dec 19 14:45:25 2014 @@ -31,6 +31,13 @@ formAuthenticator.forwardLoginFail=Unexp formAuthenticator.noErrorPage=No error page was defined for FORM authentication in context [{0}] formAuthenticator.noLoginPage=No login page was defined for FORM authentication in context [{0}] +singleSignOn.sessionExpire.engineNull=Unable to expire session [{0}] because the Engine was null +singleSignOn.sessionExpire.hostNotFound=Unable to expire session [{0}] because the Host could not be found +singleSignOn.sessionExpire.contextNotFound=Unable to expire session [{0}] because the Context could not be found +singleSignOn.sessionExpire.managerNotFound=Unable to expire session [{0}] because the Manager could not be found +singleSignOn.sessionExpire.managerError=Unable to expire session [{0}] because the Manager threw an Exception when searching for the session +singleSignOn.sessionExpire.sessionNotFound=Unable to expire session [{0}] because the Session could not be found + spnegoAuthenticator.authHeaderNoToken=The Negotiate authorization header sent by the client did not include a token spnegoAuthenticator.authHeaderNotNego=The authorization header sent by the client did not start with Negotiate spnegoAuthenticator.serviceLoginFail=Unable to login as the service principal Modified: tomcat/tc8.0.x/trunk/java/org/apache/catalina/authenticator/SingleSignOn.java URL: http://svn.apache.org/viewvc/tomcat/tc8.0.x/trunk/java/org/apache/catalina/authenticator/SingleSignOn.java?rev=1646744&r1=1646743&r2=1646744&view=diff ============================================================================== --- tomcat/tc8.0.x/trunk/java/org/apache/catalina/authenticator/SingleSignOn.java (original) +++ tomcat/tc8.0.x/trunk/java/org/apache/catalina/authenticator/SingleSignOn.java Fri Dec 19 14:45:25 2014 @@ -19,11 +19,17 @@ package org.apache.catalina.authenticato import java.io.IOException; import java.security.Principal; import java.util.Map; +import java.util.Set; import java.util.concurrent.ConcurrentHashMap; import javax.servlet.ServletException; import javax.servlet.http.Cookie; +import org.apache.catalina.Container; +import org.apache.catalina.Context; +import org.apache.catalina.Engine; +import org.apache.catalina.LifecycleException; +import org.apache.catalina.Manager; import org.apache.catalina.Realm; import org.apache.catalina.Session; import org.apache.catalina.SessionEvent; @@ -31,6 +37,9 @@ import org.apache.catalina.SessionListen import org.apache.catalina.connector.Request; import org.apache.catalina.connector.Response; import org.apache.catalina.valves.ValveBase; +import org.apache.juli.logging.Log; +import org.apache.juli.logging.LogFactory; +import org.apache.tomcat.util.res.StringManager; /** * A <strong>Valve</strong> that supports a "single sign on" user experience, @@ -53,6 +62,15 @@ import org.apache.catalina.valves.ValveB */ public class SingleSignOn extends ValveBase implements SessionListener { + private static final Log log = LogFactory.getLog(SingleSignOn.class); + private static final StringManager sm = StringManager.getManager(SingleSignOn.class); + + /* The engine at the top of the container hierarchy in which this SSO Valve + * has been placed. It is used to get back to a session object from a + * SingleSignOnSessionKey and is updated when the Valve starts and stops. + */ + private Engine engine; + //------------------------------------------------------ Constructor public SingleSignOn() { @@ -79,7 +97,7 @@ public class SingleSignOn extends ValveB * The cache of single sign on identifiers, keyed by the Session that is * associated with them. */ - protected Map<Session,String> reverse = new ConcurrentHashMap<>(); + protected Map<SingleSignOnSessionKey,String> reverse = new ConcurrentHashMap<>(); /** @@ -209,7 +227,7 @@ public class SingleSignOn extends ValveB } String ssoId = null; - ssoId = reverse.get(session); + ssoId = reverse.get(new SingleSignOnSessionKey(session)); if (ssoId == null) { return; } @@ -354,7 +372,7 @@ public class SingleSignOn extends ValveB if (sso != null) { sso.addSession(this, session); } - reverse.put(session, ssoId); + reverse.put(new SingleSignOnSessionKey(session), ssoId); } @@ -367,7 +385,7 @@ public class SingleSignOn extends ValveB */ protected void deregister(String ssoId, Session session) { - reverse.remove(session); + reverse.remove(new SingleSignOnSessionKey(session)); SingleSignOnEntry sso = cache.get(ssoId); if (sso == null) { @@ -377,8 +395,8 @@ public class SingleSignOn extends ValveB sso.removeSession(session); // see if we are the last session, if so blow away ssoId - Session sessions[] = sso.findSessions(); - if (sessions == null || sessions.length == 0) { + Set<SingleSignOnSessionKey> sessions = sso.findSessions(); + if (sessions == null || sessions.size() == 0) { cache.remove(ssoId); } } @@ -404,21 +422,54 @@ public class SingleSignOn extends ValveB } // Expire any associated sessions - Session sessions[] = sso.findSessions(); - for (int i = 0; i < sessions.length; i++) { + for (SingleSignOnSessionKey ssoKey : sso.findSessions()) { if (containerLog.isTraceEnabled()) { - containerLog.trace(" Invalidating session " + sessions[i]); + containerLog.trace(" Invalidating session " + ssoKey); } // Remove from reverse cache first to avoid recursion - reverse.remove(sessions[i]); + reverse.remove(ssoKey); // Invalidate this session - sessions[i].expire(); + expire(ssoKey); } // 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 + } + + private void expire(SingleSignOnSessionKey key) { + if (engine == null) { + log.warn(sm.getString("singleSignOn.sessionExpire.engineNull", key)); + return; + } + Container host = engine.findChild(key.getHostName()); + if (host == null) { + log.warn(sm.getString("singleSignOn.sessionExpire.hostNotFound", key)); + return; + } + Context context = (Context) host.findChild(key.getContextName()); + if (context == null) { + log.warn(sm.getString("singleSignOn.sessionExpire.contextNotFound", key)); + return; + } + Manager manager = context.getManager(); + if (manager == null) { + log.warn(sm.getString("singleSignOn.sessionExpire.managerNotFound", key)); + return; + } + Session session = null; + try { + session = manager.findSession(key.getSessionId()); + } catch (IOException e) { + log.warn(sm.getString("singleSignOn.sessionExpire.managerError", key), e); + return; + } + if (session == null) { + log.warn(sm.getString("singleSignOn.sessionExpire.sessionNotFound", key)); + return; + } + session.expire(); } @@ -558,12 +609,32 @@ public class SingleSignOn extends ValveB entry.removeSession(session); // Remove the inactive session from the 'reverse' Map. - reverse.remove(session); + reverse.remove(new SingleSignOnSessionKey(session)); // If there are not sessions left in the SingleSignOnEntry, // deregister the entry. - if (entry.findSessions().length == 0) { + if (entry.findSessions().size() == 0) { deregister(ssoId); } } + + + @Override + protected synchronized void startInternal() throws LifecycleException { + Container c = getContainer(); + while (c != null && !(c instanceof Engine)) { + c = c.getParent(); + } + if (c instanceof Engine) { + engine = (Engine) c; + } + super.startInternal(); + } + + + @Override + protected synchronized void stopInternal() throws LifecycleException { + super.stopInternal(); + engine = null; + } } Modified: tomcat/tc8.0.x/trunk/java/org/apache/catalina/authenticator/SingleSignOnEntry.java URL: http://svn.apache.org/viewvc/tomcat/tc8.0.x/trunk/java/org/apache/catalina/authenticator/SingleSignOnEntry.java?rev=1646744&r1=1646743&r2=1646744&view=diff ============================================================================== --- tomcat/tc8.0.x/trunk/java/org/apache/catalina/authenticator/SingleSignOnEntry.java (original) +++ tomcat/tc8.0.x/trunk/java/org/apache/catalina/authenticator/SingleSignOnEntry.java Fri Dec 19 14:45:25 2014 @@ -16,7 +16,11 @@ */ package org.apache.catalina.authenticator; +import java.io.IOException; +import java.io.Serializable; import java.security.Principal; +import java.util.Set; +import java.util.concurrent.ConcurrentHashMap; import javax.servlet.http.HttpServletRequest; @@ -33,17 +37,21 @@ import org.apache.catalina.Session; * @see SingleSignOn * @see AuthenticatorBase#reauthenticateFromSSO */ -public class SingleSignOnEntry -{ +public class SingleSignOnEntry implements Serializable { + + private static final long serialVersionUID = 1L; + // ------------------------------------------------------ Instance Fields protected String authType = null; protected String password = null; - protected Principal principal = null; + // Marked as transient so special handling can be applied to serialization + protected transient Principal principal = null; - protected Session sessions[] = new Session[0]; + protected ConcurrentHashMap<SingleSignOnSessionKey,SingleSignOnSessionKey> sessionKeys = + new ConcurrentHashMap<>(); protected String username = null; @@ -77,16 +85,13 @@ public class SingleSignOnEntry * the SSO session. * @param session The <code>Session</code> being associated with the SSO. */ - public synchronized void addSession(SingleSignOn sso, Session session) { - for (int i = 0; i < sessions.length; i++) { - if (session == sessions[i]) - return; + public void addSession(SingleSignOn sso, Session session) { + SingleSignOnSessionKey key = new SingleSignOnSessionKey(session); + SingleSignOnSessionKey currentKey = sessionKeys.putIfAbsent(key, key); + if (currentKey == null) { + // Session not previously added + session.addSessionListener(sso); } - Session results[] = new Session[sessions.length + 1]; - System.arraycopy(sessions, 0, results, 0, sessions.length); - results[sessions.length] = session; - sessions = results; - session.addSessionListener(sso); } /** @@ -95,21 +100,16 @@ public class SingleSignOnEntry * * @param session the <code>Session</code> to remove. */ - public synchronized void removeSession(Session session) { - Session[] nsessions = new Session[sessions.length - 1]; - for (int i = 0, j = 0; i < sessions.length; i++) { - if (session == sessions[i]) - continue; - nsessions[j++] = sessions[i]; - } - sessions = nsessions; + public void removeSession(Session session) { + SingleSignOnSessionKey key = new SingleSignOnSessionKey(session); + sessionKeys.remove(key); } /** * Returns the <code>Session</code>s associated with this SSO. */ - public synchronized Session[] findSessions() { - return (this.sessions); + public Set<SingleSignOnSessionKey> findSessions() { + return sessionKeys.keySet(); } /** @@ -182,4 +182,24 @@ public class SingleSignOnEntry this.canReauthenticate = (HttpServletRequest.BASIC_AUTH.equals(authType) || HttpServletRequest.FORM_AUTH.equals(authType)); } + + + private void writeObject(java.io.ObjectOutputStream out) throws IOException { + out.defaultWriteObject(); + if (principal instanceof Serializable) { + out.writeBoolean(true); + out.writeObject(principal); + } else { + out.writeBoolean(false); + } + } + + private void readObject(java.io.ObjectInputStream in) throws IOException, + ClassNotFoundException { + in.defaultReadObject(); + boolean hasPrincipal = in.readBoolean(); + if (hasPrincipal) { + principal = (Principal) in.readObject(); + } + } } Propchange: tomcat/tc8.0.x/trunk/java/org/apache/catalina/authenticator/SingleSignOnSessionKey.java ------------------------------------------------------------------------------ svn:eol-style = native Modified: tomcat/tc8.0.x/trunk/java/org/apache/catalina/ha/authenticator/ClusterSingleSignOn.java URL: http://svn.apache.org/viewvc/tomcat/tc8.0.x/trunk/java/org/apache/catalina/ha/authenticator/ClusterSingleSignOn.java?rev=1646744&r1=1646743&r2=1646744&view=diff ============================================================================== --- tomcat/tc8.0.x/trunk/java/org/apache/catalina/ha/authenticator/ClusterSingleSignOn.java (original) +++ tomcat/tc8.0.x/trunk/java/org/apache/catalina/ha/authenticator/ClusterSingleSignOn.java Fri Dec 19 14:45:25 2014 @@ -16,18 +16,14 @@ */ package org.apache.catalina.ha.authenticator; -import java.security.Principal; - import org.apache.catalina.Container; import org.apache.catalina.Host; import org.apache.catalina.LifecycleException; -import org.apache.catalina.Manager; -import org.apache.catalina.Session; import org.apache.catalina.authenticator.SingleSignOn; import org.apache.catalina.ha.CatalinaCluster; -import org.apache.catalina.ha.ClusterManager; import org.apache.catalina.ha.ClusterValve; -import org.apache.catalina.realm.GenericPrincipal; +import org.apache.catalina.tribes.tipis.AbstractReplicatedMap.MapOwner; +import org.apache.catalina.tribes.tipis.ReplicatedMap; import org.apache.tomcat.util.ExceptionUtils; /** @@ -49,16 +45,9 @@ import org.apache.tomcat.util.ExceptionU * * @author Fabien Carrion */ -public class ClusterSingleSignOn extends SingleSignOn implements ClusterValve { - - // ----------------------------------------------------- Instance Variables - - protected int messageNumber = 0; - - private ClusterSingleSignOnListener clusterSSOListener = null; +public class ClusterSingleSignOn extends SingleSignOn implements ClusterValve, MapOwner { - - // ------------------------------------------------------------- Properties + // -------------------------------------------------------------- Properties private CatalinaCluster cluster = null; @Override @@ -69,7 +58,24 @@ public class ClusterSingleSignOn extends } - // ------------------------------------------------------ Lifecycle Methods + private long rpcTimeout = 15000; + public long getRpcTimeout() { + return rpcTimeout; + } + public void setRpcTimeout(long rpcTimeout) { + this.rpcTimeout = rpcTimeout; + } + + + // -------------------------------------------------------- MapOwner Methods + + @Override + public void objectMadePrimary(Object key, Object value) { + // NO-OP + } + + + // ------------------------------------------------------- Lifecycle Methods /** * Start this component and implement the requirements @@ -81,8 +87,6 @@ public class ClusterSingleSignOn extends @Override protected synchronized void startInternal() throws LifecycleException { - clusterSSOListener = new ClusterSingleSignOnListener(this); - // Load the cluster component, if any try { if(cluster == null) { @@ -96,9 +100,15 @@ public class ClusterSingleSignOn extends if (cluster == null) { throw new LifecycleException( "There is no Cluster for ClusterSingleSignOn"); - } else { - getCluster().addClusterListener(clusterSSOListener); } + + ClassLoader[] cls = new ClassLoader[] { this.getClass().getClassLoader() }; + + cache = new ReplicatedMap<>(this, cluster.getChannel(), rpcTimeout, + cluster.getClusterName() + "-SSO-cache", cls); + reverse = new ReplicatedMap<>(this, cluster.getChannel(), rpcTimeout, + cluster.getClusterName() + "-SSO-reverse", cls); + } catch (Throwable t) { ExceptionUtils.handleThrowable(t); throw new LifecycleException( @@ -122,271 +132,8 @@ public class ClusterSingleSignOn extends super.stopInternal(); if (getCluster() != null) { - getCluster().removeClusterListener(clusterSSOListener); - } - } - - - // ------------------------------------------------------ Protected Methods - - /** - * Notify the cluster of the addition of a Session to - * an SSO session and associate the specified single - * sign on identifier with the specified Session on the - * local node. - * - * @param ssoId Single sign on identifier - * @param session Session to be associated - */ - @Override - protected void associate(String ssoId, Session session) { - - if (cluster != null && cluster.getMembers().length > 0) { - messageNumber++; - SingleSignOnMessage msg = - new SingleSignOnMessage(cluster.getLocalMember(), - ssoId, session.getId()); - Manager mgr = session.getManager(); - if ((mgr != null) && (mgr instanceof ClusterManager)) { - msg.setContextName(((ClusterManager) mgr).getName()); - } - - msg.setAction(SingleSignOnMessage.ADD_SESSION); - - cluster.send(msg); - - if (containerLog.isDebugEnabled()) { - containerLog.debug("SingleSignOnMessage Send with action " - + msg.getAction()); - } - } - - associateLocal(ssoId, session); - } - - - protected void associateLocal(String ssoId, Session session) { - super.associate(ssoId, session); - } - - - /** - * Notify the cluster of the removal of a Session from an - * SSO session and deregister the specified session. If it is the last - * session, then also get rid of the single sign on identifier on the - * local node. - * - * @param ssoId Single sign on identifier - * @param session Session to be deregistered - */ - @Override - protected void deregister(String ssoId, Session session) { - - if (cluster != null && cluster.getMembers().length > 0) { - messageNumber++; - SingleSignOnMessage msg = - new SingleSignOnMessage(cluster.getLocalMember(), - ssoId, session.getId()); - Manager mgr = session.getManager(); - if ((mgr != null) && (mgr instanceof ClusterManager)) { - msg.setContextName(((ClusterManager) mgr).getName()); - } - - msg.setAction(SingleSignOnMessage.DEREGISTER_SESSION); - - cluster.send(msg); - if (containerLog.isDebugEnabled()) { - containerLog.debug("SingleSignOnMessage Send with action " - + msg.getAction()); - } + ((ReplicatedMap<?,?>) cache).breakdown(); + ((ReplicatedMap<?,?>) reverse).breakdown(); } - - deregisterLocal(ssoId, session); - } - - - protected void deregisterLocal(String ssoId, Session session) { - super.deregister(ssoId, session); - } - - - /** - * Notifies the cluster that a single sign on session - * has been terminated due to a user logout, deregister - * the specified single sign on identifier, and invalidate - * any associated sessions on the local node. - * - * @param ssoId Single sign on identifier to deregister - */ - @Override - protected void deregister(String ssoId) { - - if (cluster != null && cluster.getMembers().length > 0) { - messageNumber++; - SingleSignOnMessage msg = - new SingleSignOnMessage(cluster.getLocalMember(), - ssoId, null); - msg.setAction(SingleSignOnMessage.LOGOUT_SESSION); - - cluster.send(msg); - if (containerLog.isDebugEnabled()) { - containerLog.debug("SingleSignOnMessage Send with action " - + msg.getAction()); - } - } - - deregisterLocal(ssoId); - } - - - protected void deregisterLocal(String ssoId) { - super.deregister(ssoId); - } - - - /** - * Notifies the cluster of the creation of a new SSO entry - * and 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 - * @param username Username used to authenticate this user - * @param password Password used to authenticate this user - */ - @Override - protected void register(String ssoId, Principal principal, String authType, - String username, String password) { - - if (cluster != null && cluster.getMembers().length > 0) { - messageNumber++; - SingleSignOnMessage msg = - new SingleSignOnMessage(cluster.getLocalMember(), - ssoId, null); - msg.setAction(SingleSignOnMessage.REGISTER_SESSION); - msg.setAuthType(authType); - msg.setUsername(username); - msg.setPassword(password); - - if (principal instanceof GenericPrincipal) { - msg.setPrincipal((GenericPrincipal) principal); - } - - cluster.send(msg); - if (containerLog.isDebugEnabled()) { - containerLog.debug("SingleSignOnMessage Send with action " - + msg.getAction()); - } - } - - registerLocal(ssoId, principal, authType, username, password); - } - - - protected void registerLocal(String ssoId, Principal principal, String authType, - String username, String password) { - super.register(ssoId, principal, authType, username, password); - } - - - /** - * Notifies the cluster of an update of the security credentials - * associated with an SSO session. 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 - */ - @Override - protected void update(String ssoId, Principal principal, String authType, - String username, String password) { - - if (cluster != null && cluster.getMembers().length > 0) { - messageNumber++; - SingleSignOnMessage msg = - new SingleSignOnMessage(cluster.getLocalMember(), - ssoId, null); - msg.setAction(SingleSignOnMessage.UPDATE_SESSION); - msg.setAuthType(authType); - msg.setUsername(username); - msg.setPassword(password); - - if (principal instanceof GenericPrincipal) { - msg.setPrincipal((GenericPrincipal) principal); - } - - cluster.send(msg); - if (containerLog.isDebugEnabled()) { - containerLog.debug("SingleSignOnMessage Send with action " - + msg.getAction()); - } - } - - updateLocal(ssoId, principal, authType, username, password); - } - - - protected void updateLocal(String ssoId, Principal principal, String authType, - String username, String password) { - super.update(ssoId, principal, authType, username, password); - } - - - /** - * Remove a single Session from a SingleSignOn and notify the cluster - * of the removal. 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. - */ - @Override - protected void removeSession(String ssoId, Session session) { - - if (cluster != null && cluster.getMembers().length > 0) { - messageNumber++; - SingleSignOnMessage msg = - new SingleSignOnMessage(cluster.getLocalMember(), - ssoId, session.getId()); - - Manager mgr = session.getManager(); - if ((mgr != null) && (mgr instanceof ClusterManager)) { - msg.setContextName(((ClusterManager) mgr).getName()); - } - - msg.setAction(SingleSignOnMessage.REMOVE_SESSION); - - cluster.send(msg); - if (containerLog.isDebugEnabled()) { - containerLog.debug("SingleSignOnMessage Send with action " - + msg.getAction()); - } - } - - removeSessionLocal(ssoId, session); - } - - - protected void removeSessionLocal(String ssoId, Session session) { - super.removeSession(ssoId, session); } } --------------------------------------------------------------------- To unsubscribe, e-mail: dev-unsubscr...@tomcat.apache.org For additional commands, e-mail: dev-h...@tomcat.apache.org