405422 Implement servlet3.1 spec sections 4.4.3 and 8.1.4 for new HttpSessionIdListener class
This commit is contained in:
parent
0d181d9a75
commit
f544d6e701
|
@ -23,6 +23,7 @@ import javax.servlet.ServletContextListener;
|
||||||
import javax.servlet.ServletRequestAttributeListener;
|
import javax.servlet.ServletRequestAttributeListener;
|
||||||
import javax.servlet.ServletRequestListener;
|
import javax.servlet.ServletRequestListener;
|
||||||
import javax.servlet.http.HttpSessionAttributeListener;
|
import javax.servlet.http.HttpSessionAttributeListener;
|
||||||
|
import javax.servlet.http.HttpSessionIdListener;
|
||||||
import javax.servlet.http.HttpSessionListener;
|
import javax.servlet.http.HttpSessionListener;
|
||||||
|
|
||||||
import org.eclipse.jetty.util.log.Log;
|
import org.eclipse.jetty.util.log.Log;
|
||||||
|
@ -78,7 +79,8 @@ public class WebListenerAnnotation extends DiscoveredAnnotation
|
||||||
ServletRequestListener.class.isAssignableFrom(clazz) ||
|
ServletRequestListener.class.isAssignableFrom(clazz) ||
|
||||||
ServletRequestAttributeListener.class.isAssignableFrom(clazz) ||
|
ServletRequestAttributeListener.class.isAssignableFrom(clazz) ||
|
||||||
HttpSessionListener.class.isAssignableFrom(clazz) ||
|
HttpSessionListener.class.isAssignableFrom(clazz) ||
|
||||||
HttpSessionAttributeListener.class.isAssignableFrom(clazz))
|
HttpSessionAttributeListener.class.isAssignableFrom(clazz) ||
|
||||||
|
HttpSessionIdListener.class.isAssignableFrom(clazz))
|
||||||
{
|
{
|
||||||
java.util.EventListener listener = (java.util.EventListener)clazz.newInstance();
|
java.util.EventListener listener = (java.util.EventListener)clazz.newInstance();
|
||||||
MetaData metaData = _context.getMetaData();
|
MetaData metaData = _context.getMetaData();
|
||||||
|
|
|
@ -332,6 +332,7 @@ public abstract class NoSqlSessionManager extends AbstractSessionManager impleme
|
||||||
__log.warn(e);
|
__log.warn(e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
super.renewSessionId(oldClusterId, oldNodeId, newClusterId, newNodeId);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -51,8 +51,8 @@ public abstract class AbstractSession implements AbstractSessionManager.SessionI
|
||||||
{
|
{
|
||||||
final static Logger LOG = SessionHandler.LOG;
|
final static Logger LOG = SessionHandler.LOG;
|
||||||
public final static String SESSION_KNOWN_ONLY_TO_AUTHENTICATED="org.eclipse.jetty.security.sessionKnownOnlytoAuthenticated";
|
public final static String SESSION_KNOWN_ONLY_TO_AUTHENTICATED="org.eclipse.jetty.security.sessionKnownOnlytoAuthenticated";
|
||||||
private String _clusterId; // ID unique within cluster
|
private String _clusterId; // ID without any node (ie "worker") id appended
|
||||||
private String _nodeId; // ID unique within node
|
private String _nodeId; // ID of session with node(ie "worker") id appended
|
||||||
private final AbstractSessionManager _manager;
|
private final AbstractSessionManager _manager;
|
||||||
private final Map<String,Object> _attributes=new HashMap<String, Object>();
|
private final Map<String,Object> _attributes=new HashMap<String, Object>();
|
||||||
private boolean _idChanged;
|
private boolean _idChanged;
|
||||||
|
|
|
@ -38,6 +38,7 @@ import javax.servlet.http.HttpSessionAttributeListener;
|
||||||
import javax.servlet.http.HttpSessionBindingEvent;
|
import javax.servlet.http.HttpSessionBindingEvent;
|
||||||
import javax.servlet.http.HttpSessionContext;
|
import javax.servlet.http.HttpSessionContext;
|
||||||
import javax.servlet.http.HttpSessionEvent;
|
import javax.servlet.http.HttpSessionEvent;
|
||||||
|
import javax.servlet.http.HttpSessionIdListener;
|
||||||
import javax.servlet.http.HttpSessionListener;
|
import javax.servlet.http.HttpSessionListener;
|
||||||
|
|
||||||
import org.eclipse.jetty.http.HttpCookie;
|
import org.eclipse.jetty.http.HttpCookie;
|
||||||
|
@ -107,6 +108,7 @@ public abstract class AbstractSessionManager extends AbstractLifeCycle implement
|
||||||
|
|
||||||
protected final List<HttpSessionAttributeListener> _sessionAttributeListeners = new CopyOnWriteArrayList<HttpSessionAttributeListener>();
|
protected final List<HttpSessionAttributeListener> _sessionAttributeListeners = new CopyOnWriteArrayList<HttpSessionAttributeListener>();
|
||||||
protected final List<HttpSessionListener> _sessionListeners= new CopyOnWriteArrayList<HttpSessionListener>();
|
protected final List<HttpSessionListener> _sessionListeners= new CopyOnWriteArrayList<HttpSessionListener>();
|
||||||
|
protected final List<HttpSessionIdListener> _sessionIdListeners = new CopyOnWriteArrayList<HttpSessionIdListener>();
|
||||||
|
|
||||||
protected ClassLoader _loader;
|
protected ClassLoader _loader;
|
||||||
protected ContextHandler.Context _context;
|
protected ContextHandler.Context _context;
|
||||||
|
@ -191,6 +193,8 @@ public abstract class AbstractSessionManager extends AbstractLifeCycle implement
|
||||||
_sessionAttributeListeners.add((HttpSessionAttributeListener)listener);
|
_sessionAttributeListeners.add((HttpSessionAttributeListener)listener);
|
||||||
if (listener instanceof HttpSessionListener)
|
if (listener instanceof HttpSessionListener)
|
||||||
_sessionListeners.add((HttpSessionListener)listener);
|
_sessionListeners.add((HttpSessionListener)listener);
|
||||||
|
if (listener instanceof HttpSessionIdListener)
|
||||||
|
_sessionIdListeners.add((HttpSessionIdListener)listener);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* ------------------------------------------------------------ */
|
/* ------------------------------------------------------------ */
|
||||||
|
@ -198,6 +202,7 @@ public abstract class AbstractSessionManager extends AbstractLifeCycle implement
|
||||||
{
|
{
|
||||||
_sessionAttributeListeners.clear();
|
_sessionAttributeListeners.clear();
|
||||||
_sessionListeners.clear();
|
_sessionListeners.clear();
|
||||||
|
_sessionIdListeners.clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
/* ------------------------------------------------------------ */
|
/* ------------------------------------------------------------ */
|
||||||
|
@ -990,6 +995,29 @@ public abstract class AbstractSessionManager extends AbstractLifeCycle implement
|
||||||
{
|
{
|
||||||
_checkingRemoteSessionIdEncoding=remote;
|
_checkingRemoteSessionIdEncoding=remote;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* ------------------------------------------------------------ */
|
||||||
|
/**
|
||||||
|
* Tell the HttpSessionIdListeners the id changed.
|
||||||
|
* NOTE: this method must be called LAST in subclass overrides, after the session has been updated
|
||||||
|
* with the new id.
|
||||||
|
* @see org.eclipse.jetty.server.SessionManager#renewSessionId(java.lang.String, java.lang.String, java.lang.String, java.lang.String)
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public void renewSessionId(String oldClusterId, String oldNodeId, String newClusterId, String newNodeId)
|
||||||
|
{
|
||||||
|
if (!_sessionIdListeners.isEmpty())
|
||||||
|
{
|
||||||
|
AbstractSession session = getSession(newClusterId);
|
||||||
|
HttpSessionEvent event = new HttpSessionEvent(session);
|
||||||
|
for (HttpSessionIdListener l:_sessionIdListeners)
|
||||||
|
{
|
||||||
|
l.sessionIdChanged(event, oldClusterId);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
/* ------------------------------------------------------------ */
|
/* ------------------------------------------------------------ */
|
||||||
/* ------------------------------------------------------------ */
|
/* ------------------------------------------------------------ */
|
||||||
|
|
|
@ -439,6 +439,8 @@ public class HashSessionManager extends AbstractSessionManager
|
||||||
session.setNodeId(newNodeId);
|
session.setNodeId(newNodeId);
|
||||||
session.save(); //save updated session: TODO consider only saving file if idled
|
session.save(); //save updated session: TODO consider only saving file if idled
|
||||||
sessions.put(newClusterId, session);
|
sessions.put(newClusterId, session);
|
||||||
|
|
||||||
|
super.renewSessionId(oldClusterId, oldNodeId, newClusterId, newNodeId);
|
||||||
}
|
}
|
||||||
catch (Exception e)
|
catch (Exception e)
|
||||||
{
|
{
|
||||||
|
|
|
@ -645,6 +645,8 @@ public class JDBCSessionManager extends AbstractSessionManager
|
||||||
LOG.warn(e);
|
LOG.warn(e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
super.renewSessionId(oldClusterId, oldNodeId, newClusterId, newNodeId);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -41,6 +41,7 @@ import javax.servlet.ServletSecurityElement;
|
||||||
import javax.servlet.http.HttpSessionActivationListener;
|
import javax.servlet.http.HttpSessionActivationListener;
|
||||||
import javax.servlet.http.HttpSessionAttributeListener;
|
import javax.servlet.http.HttpSessionAttributeListener;
|
||||||
import javax.servlet.http.HttpSessionBindingListener;
|
import javax.servlet.http.HttpSessionBindingListener;
|
||||||
|
import javax.servlet.http.HttpSessionIdListener;
|
||||||
import javax.servlet.http.HttpSessionListener;
|
import javax.servlet.http.HttpSessionListener;
|
||||||
|
|
||||||
import org.eclipse.jetty.security.ConstraintAware;
|
import org.eclipse.jetty.security.ConstraintAware;
|
||||||
|
@ -1058,7 +1059,8 @@ public class WebAppContext extends ServletContextHandler implements WebAppClassL
|
||||||
if ((listener instanceof HttpSessionActivationListener)
|
if ((listener instanceof HttpSessionActivationListener)
|
||||||
|| (listener instanceof HttpSessionAttributeListener)
|
|| (listener instanceof HttpSessionAttributeListener)
|
||||||
|| (listener instanceof HttpSessionBindingListener)
|
|| (listener instanceof HttpSessionBindingListener)
|
||||||
|| (listener instanceof HttpSessionListener))
|
|| (listener instanceof HttpSessionListener)
|
||||||
|
|| (listener instanceof HttpSessionIdListener))
|
||||||
{
|
{
|
||||||
if (_sessionHandler!=null)
|
if (_sessionHandler!=null)
|
||||||
_sessionHandler.addEventListener(listener);
|
_sessionHandler.addEventListener(listener);
|
||||||
|
@ -1072,7 +1074,8 @@ public class WebAppContext extends ServletContextHandler implements WebAppClassL
|
||||||
if ((listener instanceof HttpSessionActivationListener)
|
if ((listener instanceof HttpSessionActivationListener)
|
||||||
|| (listener instanceof HttpSessionAttributeListener)
|
|| (listener instanceof HttpSessionAttributeListener)
|
||||||
|| (listener instanceof HttpSessionBindingListener)
|
|| (listener instanceof HttpSessionBindingListener)
|
||||||
|| (listener instanceof HttpSessionListener))
|
|| (listener instanceof HttpSessionListener)
|
||||||
|
|| (listener instanceof HttpSessionIdListener))
|
||||||
{
|
{
|
||||||
if (_sessionHandler!=null)
|
if (_sessionHandler!=null)
|
||||||
_sessionHandler.removeEventListener(listener);
|
_sessionHandler.removeEventListener(listener);
|
||||||
|
|
|
@ -32,11 +32,14 @@ import javax.servlet.http.HttpServlet;
|
||||||
import javax.servlet.http.HttpServletRequest;
|
import javax.servlet.http.HttpServletRequest;
|
||||||
import javax.servlet.http.HttpServletResponse;
|
import javax.servlet.http.HttpServletResponse;
|
||||||
import javax.servlet.http.HttpSession;
|
import javax.servlet.http.HttpSession;
|
||||||
|
import javax.servlet.http.HttpSessionEvent;
|
||||||
|
import javax.servlet.http.HttpSessionIdListener;
|
||||||
|
|
||||||
import org.eclipse.jetty.client.HttpClient;
|
import org.eclipse.jetty.client.HttpClient;
|
||||||
import org.eclipse.jetty.client.api.ContentResponse;
|
import org.eclipse.jetty.client.api.ContentResponse;
|
||||||
import org.eclipse.jetty.client.api.Request;
|
import org.eclipse.jetty.client.api.Request;
|
||||||
import org.eclipse.jetty.servlet.ServletContextHandler;
|
import org.eclipse.jetty.servlet.ServletContextHandler;
|
||||||
|
import org.eclipse.jetty.webapp.WebAppContext;
|
||||||
|
|
||||||
|
|
||||||
public abstract class AbstractSessionRenewTest
|
public abstract class AbstractSessionRenewTest
|
||||||
|
@ -49,8 +52,11 @@ public abstract class AbstractSessionRenewTest
|
||||||
String servletMapping = "/server";
|
String servletMapping = "/server";
|
||||||
int scavengePeriod = 3;
|
int scavengePeriod = 3;
|
||||||
AbstractTestServer server = createServer(0, 1, scavengePeriod);
|
AbstractTestServer server = createServer(0, 1, scavengePeriod);
|
||||||
ServletContextHandler context = server.addContext(contextPath);
|
WebAppContext context = server.addWebAppContext(".", contextPath);
|
||||||
context.addServlet(TestServlet.class, servletMapping);
|
context.addServlet(TestServlet.class, servletMapping);
|
||||||
|
TestHttpSessionIdListener testListener = new TestHttpSessionIdListener();
|
||||||
|
context.addEventListener(testListener);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
HttpClient client = new HttpClient();
|
HttpClient client = new HttpClient();
|
||||||
|
@ -67,6 +73,7 @@ public abstract class AbstractSessionRenewTest
|
||||||
|
|
||||||
String sessionCookie = response.getHeaders().getStringField("Set-Cookie");
|
String sessionCookie = response.getHeaders().getStringField("Set-Cookie");
|
||||||
assertTrue(sessionCookie != null);
|
assertTrue(sessionCookie != null);
|
||||||
|
assertFalse(testListener.isCalled());
|
||||||
|
|
||||||
//make a request to change the sessionid
|
//make a request to change the sessionid
|
||||||
Request request = client.newRequest("http://localhost:" + port + contextPath + servletMapping + "?action=renew");
|
Request request = client.newRequest("http://localhost:" + port + contextPath + servletMapping + "?action=renew");
|
||||||
|
@ -76,6 +83,7 @@ public abstract class AbstractSessionRenewTest
|
||||||
String renewSessionCookie = renewResponse.getHeaders().getStringField("Set-Cookie");
|
String renewSessionCookie = renewResponse.getHeaders().getStringField("Set-Cookie");
|
||||||
assertNotNull(renewSessionCookie);
|
assertNotNull(renewSessionCookie);
|
||||||
assertNotSame(sessionCookie, renewSessionCookie);
|
assertNotSame(sessionCookie, renewSessionCookie);
|
||||||
|
assertTrue(testListener.isCalled());
|
||||||
}
|
}
|
||||||
finally
|
finally
|
||||||
{
|
{
|
||||||
|
@ -84,9 +92,30 @@ public abstract class AbstractSessionRenewTest
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
public static class TestHttpSessionIdListener implements HttpSessionIdListener
|
||||||
|
{
|
||||||
|
boolean called = false;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void sessionIdChanged(HttpSessionEvent event, String oldSessionId)
|
||||||
|
{
|
||||||
|
assertNotNull(event.getSession());
|
||||||
|
assertNotSame(oldSessionId, event.getSession().getId());
|
||||||
|
called = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean isCalled()
|
||||||
|
{
|
||||||
|
return called;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
public static class TestServlet extends HttpServlet
|
public static class TestServlet extends HttpServlet
|
||||||
{
|
{
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException
|
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException
|
||||||
{
|
{
|
||||||
|
|
Loading…
Reference in New Issue