// // ======================================================================== // Copyright (c) 1995-2014 Mort Bay Consulting Pty. Ltd. // ------------------------------------------------------------------------ // All rights reserved. This program and the accompanying materials // are made available under the terms of the Eclipse Public License v1.0 // and Apache License v2.0 which accompanies this distribution. // // The Eclipse Public License is available at // http://www.eclipse.org/legal/epl-v10.html // // The Apache License v2.0 is available at // http://www.opensource.org/licenses/apache2.0.php // // You may elect to redistribute this code under either of these licenses. // ======================================================================== // package org.eclipse.jetty.server.session; import static java.lang.Math.round; import java.util.Arrays; import java.util.Collections; import java.util.Enumeration; import java.util.EventListener; import java.util.HashSet; import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.Set; import java.util.concurrent.CopyOnWriteArrayList; import javax.servlet.ServletRequest; import javax.servlet.SessionCookieConfig; import javax.servlet.SessionTrackingMode; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpSession; import javax.servlet.http.HttpSessionAttributeListener; import javax.servlet.http.HttpSessionBindingEvent; import javax.servlet.http.HttpSessionContext; import javax.servlet.http.HttpSessionEvent; import javax.servlet.http.HttpSessionListener; import org.eclipse.jetty.http.HttpCookie; import org.eclipse.jetty.server.AbstractConnector; import org.eclipse.jetty.server.Request; import org.eclipse.jetty.server.Server; import org.eclipse.jetty.server.SessionIdManager; import org.eclipse.jetty.server.SessionManager; import org.eclipse.jetty.server.handler.ContextHandler; import org.eclipse.jetty.util.component.AbstractLifeCycle; import org.eclipse.jetty.util.log.Logger; import org.eclipse.jetty.util.statistic.CounterStatistic; import org.eclipse.jetty.util.statistic.SampleStatistic; /* ------------------------------------------------------------ */ /** * An Abstract implementation of SessionManager. The partial implementation of * SessionManager interface provides the majority of the handling required to * implement a SessionManager. Concrete implementations of SessionManager based * on AbstractSessionManager need only implement the newSession method to return * a specialised version of the Session inner class that provides an attribute * Map. *
*/
@SuppressWarnings("deprecation")
public abstract class AbstractSessionManager extends AbstractLifeCycle implements SessionManager
{
final static Logger __log = SessionHandler.LOG;
public Set
*
* According to SessionCookieConfig javadoc, case 1 can be used when:
* "... even though the request that initiated the session came over HTTP,
* is to support a topology where the web container is front-ended by an
* SSL offloading load balancer. In this case, the traffic between the client
* and the load balancer will be over HTTPS, whereas the traffic between the
* load balancer and the web container will be over HTTP."
*
* For case 2, you can use _secureRequestOnly to determine if you want the
* Servlet Spec 3.0 default behaviour when SessionCookieConfig.setSecure==false,
* which is:
* "they shall be marked as secure only if the request that initiated the
* corresponding session was also secure"
*
* The default for _secureRequestOnly is true, which gives the above behaviour. If
* you set it to false, then a session cookie is NEVER marked as secure, even if
* the initiating request was secure.
*
* @see org.eclipse.jetty.server.SessionManager#getSessionCookie(javax.servlet.http.HttpSession, java.lang.String, boolean)
*/
public HttpCookie getSessionCookie(HttpSession session, String contextPath, boolean requestIsSecure)
{
if (isUsingCookies())
{
String sessionPath = (_sessionPath==null) ? contextPath : _sessionPath;
sessionPath = (sessionPath==null||sessionPath.length()==0) ? "/" : sessionPath;
String id = getNodeId(session);
HttpCookie cookie = null;
if (_sessionComment == null)
{
cookie = new HttpCookie(
_sessionCookie,
id,
_sessionDomain,
sessionPath,
_cookieConfig.getMaxAge(),
_cookieConfig.isHttpOnly(),
_cookieConfig.isSecure() || (isSecureRequestOnly() && requestIsSecure));
}
else
{
cookie = new HttpCookie(
_sessionCookie,
id,
_sessionDomain,
sessionPath,
_cookieConfig.getMaxAge(),
_cookieConfig.isHttpOnly(),
_cookieConfig.isSecure() || (isSecureRequestOnly() && requestIsSecure),
_sessionComment,
1);
}
return cookie;
}
return null;
}
public String getSessionDomain()
{
return _sessionDomain;
}
/* ------------------------------------------------------------ */
/**
* @return Returns the sessionHandler.
*/
public SessionHandler getSessionHandler()
{
return _sessionHandler;
}
/* ------------------------------------------------------------ */
/**
* @deprecated Need to review if it is needed.
*/
@SuppressWarnings("rawtypes")
public Map getSessionMap()
{
throw new UnsupportedOperationException();
}
/* ------------------------------------------------------------ */
public int getSessions()
{
return (int)_sessionsStats.getCurrent();
}
/* ------------------------------------------------------------ */
public String getSessionIdPathParameterName()
{
return _sessionIdPathParameterName;
}
/* ------------------------------------------------------------ */
public String getSessionIdPathParameterNamePrefix()
{
return _sessionIdPathParameterNamePrefix;
}
/* ------------------------------------------------------------ */
/**
* @return Returns the usingCookies.
*/
public boolean isUsingCookies()
{
return _usingCookies;
}
/* ------------------------------------------------------------ */
public boolean isValid(HttpSession session)
{
AbstractSession s = ((SessionIf)session).getSession();
return s.isValid();
}
/* ------------------------------------------------------------ */
public String getClusterId(HttpSession session)
{
AbstractSession s = ((SessionIf)session).getSession();
return s.getClusterId();
}
/* ------------------------------------------------------------ */
public String getNodeId(HttpSession session)
{
AbstractSession s = ((SessionIf)session).getSession();
return s.getNodeId();
}
/* ------------------------------------------------------------ */
/**
* Create a new HttpSession for a request
*/
public HttpSession newHttpSession(HttpServletRequest request)
{
AbstractSession session=newSession(request);
session.setMaxInactiveInterval(_dftMaxIdleSecs);
addSession(session,true);
return session;
}
/* ------------------------------------------------------------ */
public void removeEventListener(EventListener listener)
{
if (listener instanceof HttpSessionAttributeListener)
_sessionAttributeListeners.remove(listener);
if (listener instanceof HttpSessionListener)
_sessionListeners.remove(listener);
}
/* ------------------------------------------------------------ */
/**
* @see #statsReset()
*/
@Deprecated
public void resetStats()
{
statsReset();
}
/* ------------------------------------------------------------ */
/**
* Reset statistics values
*/
public void statsReset()
{
_sessionsStats.reset(getSessions());
_sessionTimeStats.reset();
}
/* ------------------------------------------------------------ */
/**
* @param httpOnly
* The httpOnly to set.
*/
public void setHttpOnly(boolean httpOnly)
{
_httpOnly=httpOnly;
}
/* ------------------------------------------------------------ */
/**
* @param metaManager The metaManager used for cross context session management.
* @deprecated use {@link #setSessionIdManager(SessionIdManager)}
*/
public void setIdManager(SessionIdManager metaManager)
{
setSessionIdManager(metaManager);
}
/* ------------------------------------------------------------ */
/**
* @param metaManager The metaManager used for cross context session management.
*/
public void setSessionIdManager(SessionIdManager metaManager)
{
_sessionIdManager=metaManager;
}
/* ------------------------------------------------------------ */
/**
* @param seconds
*/
public void setMaxInactiveInterval(int seconds)
{
_dftMaxIdleSecs=seconds;
}
/* ------------------------------------------------------------ */
public void setRefreshCookieAge(int ageInSeconds)
{
_refreshCookieAge=ageInSeconds;
}
public void setSessionCookie(String cookieName)
{
_sessionCookie=cookieName;
}
/* ------------------------------------------------------------ */
/**
* @param sessionHandler
* The sessionHandler to set.
*/
public void setSessionHandler(SessionHandler sessionHandler)
{
_sessionHandler=sessionHandler;
}
/* ------------------------------------------------------------ */
public void setSessionIdPathParameterName(String param)
{
_sessionIdPathParameterName =(param==null||"none".equals(param))?null:param;
_sessionIdPathParameterNamePrefix =(param==null||"none".equals(param))?null:(";"+ _sessionIdPathParameterName +"=");
}
/* ------------------------------------------------------------ */
/**
* @param usingCookies
* The usingCookies to set.
*/
public void setUsingCookies(boolean usingCookies)
{
_usingCookies=usingCookies;
}
protected abstract void addSession(AbstractSession session);
/* ------------------------------------------------------------ */
/**
* Add the session Registers the session with this manager and registers the
* session ID with the sessionIDManager;
*/
protected void addSession(AbstractSession session, boolean created)
{
synchronized (_sessionIdManager)
{
_sessionIdManager.addSession(session);
addSession(session);
}
if (created)
{
_sessionsStats.increment();
if (_sessionListeners!=null)
{
HttpSessionEvent event=new HttpSessionEvent(session);
for (HttpSessionListener listener : _sessionListeners)
listener.sessionCreated(event);
}
}
}
/* ------------------------------------------------------------ */
/**
* Get a known existing session
* @param idInCluster The session ID in the cluster, stripped of any worker name.
* @return A Session or null if none exists.
*/
public abstract AbstractSession getSession(String idInCluster);
protected abstract void invalidateSessions() throws Exception;
/* ------------------------------------------------------------ */
/**
* Create a new session instance
* @param request
* @return the new session
*/
protected abstract AbstractSession newSession(HttpServletRequest request);
/* ------------------------------------------------------------ */
/**
* @return true if the cluster node id (worker id) is returned as part of the session id by {@link HttpSession#getId()}. Default is false.
*/
public boolean isNodeIdInSessionId()
{
return _nodeIdInSessionId;
}
/* ------------------------------------------------------------ */
/**
* @param nodeIdInSessionId true if the cluster node id (worker id) will be returned as part of the session id by {@link HttpSession#getId()}. Default is false.
*/
public void setNodeIdInSessionId(boolean nodeIdInSessionId)
{
_nodeIdInSessionId=nodeIdInSessionId;
}
/* ------------------------------------------------------------ */
/** Remove session from manager
* @param session The session to remove
* @param invalidate True if {@link HttpSessionListener#sessionDestroyed(HttpSessionEvent)} and
* {@link SessionIdManager#invalidateAll(String)} should be called.
*/
public void removeSession(HttpSession session, boolean invalidate)
{
AbstractSession s = ((SessionIf)session).getSession();
removeSession(s,invalidate);
}
/* ------------------------------------------------------------ */
/** Remove session from manager
* @param session The session to remove
* @param invalidate True if {@link HttpSessionListener#sessionDestroyed(HttpSessionEvent)} and
* {@link SessionIdManager#invalidateAll(String)} should be called.
*/
public void removeSession(AbstractSession session, boolean invalidate)
{
// Remove session from context and global maps
boolean removed = removeSession(session.getClusterId());
if (removed)
{
_sessionsStats.decrement();
_sessionTimeStats.set(round((System.currentTimeMillis() - session.getCreationTime())/1000.0));
// Remove session from all context and global id maps
_sessionIdManager.removeSession(session);
if (invalidate)
_sessionIdManager.invalidateAll(session.getClusterId());
if (invalidate && _sessionListeners!=null)
{
HttpSessionEvent event=new HttpSessionEvent(session);
for (HttpSessionListener listener : _sessionListeners)
listener.sessionDestroyed(event);
}
}
}
/* ------------------------------------------------------------ */
protected abstract boolean removeSession(String idInCluster);
/* ------------------------------------------------------------ */
/**
* @return maximum amount of time session remained valid
*/
public long getSessionTimeMax()
{
return _sessionTimeStats.getMax();
}
/* ------------------------------------------------------------ */
public Set