Skip to content

Commit

Permalink
Issue #12070 fix session lastAccessedTime and isNew
Browse files Browse the repository at this point in the history
  • Loading branch information
janbartel committed Jul 23, 2024
1 parent 58d651a commit e20762d
Show file tree
Hide file tree
Showing 3 changed files with 174 additions and 6 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -441,6 +441,70 @@ public void testSessionCreateForwardAndInvalidate() throws Exception
}
}

/**
* Test creating a session in a request and then invalidating it in another request
*/
@Test
public void testSessionSimpleCreateInvalidate() throws Exception
{
String contextPath = "";
String servletMapping = "/server";
int inactivePeriod = -1; //immortal session
int scavengePeriod = 3;
DefaultSessionCacheFactory cacheFactory = new DefaultSessionCacheFactory();
cacheFactory.setEvictionPolicy(SessionCache.NEVER_EVICT);
cacheFactory.setSaveOnCreate(true);
cacheFactory.setFlushOnResponseCommit(true); //ensure session saved before response returned
SessionDataStoreFactory storeFactory = new TestSessionDataStoreFactory();
SessionTestSupport server1 = new SessionTestSupport(0, inactivePeriod, scavengePeriod, cacheFactory, storeFactory);
TestServlet servlet = new TestServlet();
ServletHolder holder = new ServletHolder(servlet);
ServletContextHandler contextHandler = server1.addContext(contextPath);
contextHandler.addServlet(holder, servletMapping);
servlet.setStore(contextHandler.getSessionHandler().getSessionCache().getSessionDataStore());
server1.start();
int port1 = server1.getPort();

try (StacklessLogging stackless = new StacklessLogging(CreationTest.class.getPackage()))
{
HttpClient client = new HttpClient();
client.start();
String url = "http://localhost:" + port1 + contextPath + servletMapping + "?action=create";

//make a request to set up a session on the server
ContentResponse response = client.GET(url);
assertEquals(HttpServletResponse.SC_OK, response.getStatus());
//Ensure session handling is finished
Awaitility.waitAtMost(5, TimeUnit.SECONDS).until(() -> contextHandler.getSessionHandler().getSessionCache().getSessionDataStore().exists(servlet._id));

//make a request to re-obtain the session on the server
Request request = client.newRequest("http://localhost:" + port1 + contextPath + servletMapping + "?action=test");
response = request.send();
assertEquals(HttpServletResponse.SC_OK, response.getStatus());
Awaitility.waitAtMost(5, TimeUnit.SECONDS).until(() -> contextHandler.getSessionHandler().getSessionCache().getSessionDataStore().exists(servlet._id));
//at this point the last accessed time should be the creation time
long lastAccessedTime = servlet._lastAccessedTime;
assertEquals(lastAccessedTime, servlet._creationTime);

//make another request to re-obtain the session on the server
request = client.newRequest("http://localhost:" + port1 + contextPath + servletMapping + "?action=test");
response = request.send();
assertEquals(HttpServletResponse.SC_OK, response.getStatus());
Awaitility.waitAtMost(5, TimeUnit.SECONDS).until(() -> contextHandler.getSessionHandler().getSessionCache().getSessionDataStore().exists(servlet._id));
//check that the lastAccessedTime is being updated
assertTrue(lastAccessedTime < servlet._lastAccessedTime);

//make a request to invalidate it
request = client.newRequest("http://localhost:" + port1 + contextPath + servletMapping + "?action=invalidate");
response = request.send();
assertEquals(HttpServletResponse.SC_OK, response.getStatus());
}
finally
{
server1.stop();
}
}

public static class MySessionListener implements HttpSessionListener
{
@Override
Expand All @@ -460,6 +524,8 @@ public static class TestServlet extends HttpServlet
private static final long serialVersionUID = 1L;
public String _id = null;
public SessionDataStore _store;
public long _lastAccessedTime;
public long _creationTime;

public void setStore(SessionDataStore store)
{
Expand All @@ -475,6 +541,7 @@ protected void doGet(HttpServletRequest request, HttpServletResponse httpServlet
case "forward" ->
{
HttpSession session = createAndSaveSessionId(request);
assertTrue(session.isNew());
ServletContext contextB = getServletContext().getContext("/contextB");
RequestDispatcher dispatcherB = contextB.getRequestDispatcher(request.getServletPath());
dispatcherB.forward(request, httpServletResponse);
Expand All @@ -488,7 +555,7 @@ protected void doGet(HttpServletRequest request, HttpServletResponse httpServlet
case "forwardc" ->
{
HttpSession session = createAndSaveSessionId(request);

assertTrue(session.isNew());
//forward to contextC
ServletContext contextC = getServletContext().getContext("/contextC");
RequestDispatcher dispatcherC = contextC.getRequestDispatcher(request.getServletPath());
Expand All @@ -498,7 +565,7 @@ protected void doGet(HttpServletRequest request, HttpServletResponse httpServlet
{
HttpSession session = createAndSaveSessionId(request);
assertNotNull(session);

assertTrue(session.isNew());
ServletContext contextB = getServletContext().getContext("/contextB");
RequestDispatcher dispatcherB = contextB.getRequestDispatcher(request.getServletPath());
dispatcherB.forward(request, httpServletResponse);
Expand All @@ -509,14 +576,27 @@ protected void doGet(HttpServletRequest request, HttpServletResponse httpServlet
assertNotNull(_id);
HttpSession session = request.getSession(false);
assertNotNull(session);
_lastAccessedTime = session.getLastAccessedTime();
assertFalse(session.isNew());
assertNotNull(session.getAttribute("value")); //check we see our previous session
assertNull(session.getAttribute("B")); //check we don't see stuff from other contexts
assertNull(session.getAttribute("C"));
}
case "invalidate" ->
{
HttpSession session = request.getSession(false);
assertNotNull(session);
_id = session.getId();
assertFalse(session.isNew());
session.invalidate();
assertNull(request.getSession(false));
}
case "create", "createinv", "createinvcreate" ->
{
currentRequest.set(request);
HttpSession session = createAndSaveSessionId(request);
assertTrue(session.isNew());
_creationTime = session.getCreationTime();
String check = request.getParameter("check");
if (!StringUtil.isBlank(check) && _store != null)
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -520,7 +520,10 @@ public void doScope(String target, Request baseRequest, HttpServletRequest reque
coreRequest.setSessionManager(_sessionManager);
coreRequest.setRequestedSession(currentRequestedSession);
if (currentRequestedSession != null)
{
coreRequest.setManagedSession(currentRequestedSession.session());
currentSession = currentRequestedSession.session();
}
break;
}
case ASYNC:
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -435,6 +435,72 @@ public void testSessionCreateForwardAndInvalidate() throws Exception
}
}

/**
* Test creating a session in a request and then invalidating it in another request
* @throws Exception
*/
@Test
public void testSessionSimpleCreateInvalidate() throws Exception
{
String contextPath = "";
String servletMapping = "/server";
int inactivePeriod = -1; //immortal session
int scavengePeriod = 3;
DefaultSessionCacheFactory cacheFactory = new DefaultSessionCacheFactory();
cacheFactory.setEvictionPolicy(SessionCache.NEVER_EVICT);
cacheFactory.setSaveOnCreate(true);
cacheFactory.setFlushOnResponseCommit(true); //ensure session saved before response returned
SessionDataStoreFactory storeFactory = new TestSessionDataStoreFactory();
SessionTestSupport server1 = new SessionTestSupport(0, inactivePeriod, scavengePeriod, cacheFactory, storeFactory);
TestServlet servlet = new TestServlet();
ServletHolder holder = new ServletHolder(servlet);
ServletContextHandler contextHandler = server1.addContext(contextPath);
contextHandler.addServlet(holder, servletMapping);
servlet.setStore(contextHandler.getSessionHandler().getSessionManager().getSessionCache().getSessionDataStore());
server1.start();
int port1 = server1.getPort();

try (StacklessLogging stackless = new StacklessLogging(CreationTest.class.getPackage()))
{
HttpClient client = new HttpClient();
client.start();
String url = "http://localhost:" + port1 + contextPath + servletMapping + "?action=create";

//make a request to set up a session on the server
ContentResponse response = client.GET(url);
assertEquals(HttpServletResponse.SC_OK, response.getStatus());
//Ensure session handling is finished
Awaitility.waitAtMost(5, TimeUnit.SECONDS).until(() -> contextHandler.getSessionHandler().getSessionManager().getSessionCache().getSessionDataStore().exists(servlet._id));

//make a request to re-obtain the session on the server
Request request = client.newRequest("http://localhost:" + port1 + contextPath + servletMapping + "?action=test");
response = request.send();
assertEquals(HttpServletResponse.SC_OK, response.getStatus());
Awaitility.waitAtMost(5, TimeUnit.SECONDS).until(() -> contextHandler.getSessionHandler().getSessionManager().getSessionCache().getSessionDataStore().exists(servlet._id));
//at this point the last accessed time should be the creation time
long lastAccessedTime = servlet._lastAccessedTime;
assertEquals(lastAccessedTime, servlet._creationTime);

//make another request to re-obtain the session on the server
request = client.newRequest("http://localhost:" + port1 + contextPath + servletMapping + "?action=test");
response = request.send();
assertEquals(HttpServletResponse.SC_OK, response.getStatus());
Awaitility.waitAtMost(5, TimeUnit.SECONDS).until(() -> contextHandler.getSessionHandler().getSessionManager().getSessionCache().getSessionDataStore().exists(servlet._id));
//check that the lastAccessedTime is being updated
assertTrue(lastAccessedTime < servlet._lastAccessedTime);

//make a request to invalidate it
request = client.newRequest("http://localhost:" + port1 + contextPath + servletMapping + "?action=invalidate");
response = request.send();
assertEquals(HttpServletResponse.SC_OK, response.getStatus());
}
finally
{
server1.stop();
}

}

public static class MySessionListener implements HttpSessionListener
{
@Override
Expand All @@ -454,6 +520,8 @@ public static class TestServlet extends HttpServlet
private static final long serialVersionUID = 1L;
public String _id = null;
public SessionDataStore _store;
public long _lastAccessedTime;
public long _creationTime;

public void setStore(SessionDataStore store)
{
Expand All @@ -469,6 +537,7 @@ protected void doGet(HttpServletRequest request, HttpServletResponse httpServlet
case "forward" ->
{
HttpSession session = createAndSaveSessionId(request);
assertTrue(session.isNew());

ServletContext contextB = getServletContext().getContext("/contextB");
RequestDispatcher dispatcherB = contextB.getRequestDispatcher(request.getServletPath());
Expand All @@ -482,6 +551,7 @@ protected void doGet(HttpServletRequest request, HttpServletResponse httpServlet
case "forwardinv" ->
{
HttpSession session = createAndSaveSessionId(request);
assertTrue(session.isNew());

ServletContext contextB = getServletContext().getContext("/contextB");
RequestDispatcher dispatcherB = contextB.getRequestDispatcher(request.getServletPath());
Expand All @@ -491,23 +561,38 @@ protected void doGet(HttpServletRequest request, HttpServletResponse httpServlet
case "forwardc" ->
{
HttpSession session = createAndSaveSessionId(request);
//forward to contextC
ServletContext contextC = getServletContext().getContext("/contextC");
RequestDispatcher dispatcherC = contextC.getRequestDispatcher(request.getServletPath());
dispatcherC.forward(request, httpServletResponse);
assertTrue(session.isNew());
//forward to contextC
ServletContext contextC = getServletContext().getContext("/contextC");
RequestDispatcher dispatcherC = contextC.getRequestDispatcher(request.getServletPath());
dispatcherC.forward(request, httpServletResponse);
}
case "test" ->
{
HttpSession session = request.getSession(false);
assertNotNull(session);
_id = session.getId();
_lastAccessedTime = session.getLastAccessedTime();
assertFalse(session.isNew());
assertNotNull(session.getAttribute("value")); //check we see the session we created earlier
assertNull(session.getAttribute("B")); //check we don't see stuff from other contexts
assertNull(session.getAttribute("C"));
}
case "invalidate" ->
{
HttpSession session = request.getSession(false);
assertNotNull(session);
_id = session.getId();
assertFalse(session.isNew());
session.invalidate();
assertNull(request.getSession(false));
}
case "create", "createinv", "createinvcreate" ->
{
currentRequest.set(request);
HttpSession session = createAndSaveSessionId(request);
assertTrue(session.isNew());
_creationTime = session.getCreationTime();
String check = request.getParameter("check");
if (!StringUtil.isBlank(check) && _store != null)
{
Expand Down

0 comments on commit e20762d

Please sign in to comment.