From 2cfa02e3c76f1af1467745ab97f707e13506e816 Mon Sep 17 00:00:00 2001 From: Thomas Bracher Date: Fri, 29 Jan 2021 17:21:14 +0100 Subject: [PATCH 1/2] make sure the session is committed only once per request --- .../web/http/SessionRepositoryFilter.java | 6 +++++ .../http/SessionRepositoryFilterTests.java | 24 +++++++++++++++++++ 2 files changed, 30 insertions(+) diff --git a/spring-session-core/src/main/java/org/springframework/session/web/http/SessionRepositoryFilter.java b/spring-session-core/src/main/java/org/springframework/session/web/http/SessionRepositoryFilter.java index c12e80081..10bff0b9a 100644 --- a/spring-session-core/src/main/java/org/springframework/session/web/http/SessionRepositoryFilter.java +++ b/spring-session-core/src/main/java/org/springframework/session/web/http/SessionRepositoryFilter.java @@ -203,6 +203,8 @@ private final class SessionRepositoryRequestWrapper extends HttpServletRequestWr private boolean requestedSessionInvalidated; + private boolean sessionCommitted; + private SessionRepositoryRequestWrapper(HttpServletRequest request, HttpServletResponse response) { super(request); this.response = response; @@ -213,6 +215,9 @@ private SessionRepositoryRequestWrapper(HttpServletRequest request, HttpServletR * and persist the Session. */ private void commitSession() { + if (this.sessionCommitted) { + return; + } HttpSessionWrapper wrappedSession = getCurrentSession(); if (wrappedSession == null) { if (isInvalidateClientSession()) { @@ -228,6 +233,7 @@ private void commitSession() { SessionRepositoryFilter.this.httpSessionIdResolver.setSessionId(this, this.response, sessionId); } } + this.sessionCommitted = true; } @SuppressWarnings("unchecked") diff --git a/spring-session-core/src/test/java/org/springframework/session/web/http/SessionRepositoryFilterTests.java b/spring-session-core/src/test/java/org/springframework/session/web/http/SessionRepositoryFilterTests.java index 7b2be3241..127863290 100644 --- a/spring-session-core/src/test/java/org/springframework/session/web/http/SessionRepositoryFilterTests.java +++ b/spring-session-core/src/test/java/org/springframework/session/web/http/SessionRepositoryFilterTests.java @@ -1321,6 +1321,30 @@ public void doFilter(HttpServletRequest wrappedRequest, HttpServletResponse wrap verifyNoMoreInteractions(sessionRepository); } + @Test + void committingTwiceHasNoEffect() throws Exception { + MapSession session = this.sessionRepository.createSession(); + this.sessionRepository.save(session); + SessionRepository sessionRepository = spy(this.sessionRepository); + setSessionCookie(session.getId()); + + this.filter = new SessionRepositoryFilter<>(sessionRepository); + + doFilter(new DoInFilter() { + @Override + public void doFilter(HttpServletRequest wrappedRequest, HttpServletResponse wrappedResponse) + throws ServletException, IOException { + wrappedRequest.getSession(false); + wrappedRequest.getRequestDispatcher("/").include(wrappedRequest, wrappedResponse); + wrappedRequest.getRequestDispatcher("/").include(wrappedRequest, wrappedResponse); + } + }); + + verify(sessionRepository, times(2)).findById(eq(session.getId())); + verify(sessionRepository).save(any()); + verifyNoMoreInteractions(sessionRepository); + } + // --- order @Test From b54c3df616558b61c0a85501faa5a2308117954f Mon Sep 17 00:00:00 2001 From: Thomas Bracher Date: Wed, 3 Mar 2021 12:47:14 +0100 Subject: [PATCH 2/2] alternative to use clear session chache only once --- .../session/web/http/SessionRepositoryFilter.java | 14 +++++++++----- .../web/http/SessionRepositoryFilterTests.java | 2 +- 2 files changed, 10 insertions(+), 6 deletions(-) diff --git a/spring-session-core/src/main/java/org/springframework/session/web/http/SessionRepositoryFilter.java b/spring-session-core/src/main/java/org/springframework/session/web/http/SessionRepositoryFilter.java index 10bff0b9a..26a840855 100644 --- a/spring-session-core/src/main/java/org/springframework/session/web/http/SessionRepositoryFilter.java +++ b/spring-session-core/src/main/java/org/springframework/session/web/http/SessionRepositoryFilter.java @@ -141,7 +141,7 @@ protected void doFilterInternal(HttpServletRequest request, HttpServletResponse filterChain.doFilter(wrappedRequest, wrappedResponse); } finally { - wrappedRequest.commitSession(); + wrappedRequest.commitSession(true); } } @@ -176,7 +176,7 @@ private final class SessionRepositoryResponseWrapper extends OnCommittedResponse @Override protected void onResponseCommitted() { - this.request.commitSession(); + this.request.commitSession(true); } } @@ -213,8 +213,10 @@ private SessionRepositoryRequestWrapper(HttpServletRequest request, HttpServletR /** * Uses the {@link HttpSessionIdResolver} to write the session id to the response * and persist the Session. + * @param clearCache clear the cache in case used when committing before the end + * of the request processing */ - private void commitSession() { + private void commitSession(boolean clearCache) { if (this.sessionCommitted) { return; } @@ -226,7 +228,9 @@ private void commitSession() { } else { S session = wrappedSession.getSession(); - clearRequestedSessionCache(); + if (clearCache) { + clearRequestedSessionCache(); + } SessionRepositoryFilter.this.sessionRepository.save(session); String sessionId = session.getId(); if (!isRequestedSessionIdValid() || !sessionId.equals(getRequestedSessionId())) { @@ -415,7 +419,7 @@ public void forward(ServletRequest request, ServletResponse response) throws Ser @Override public void include(ServletRequest request, ServletResponse response) throws ServletException, IOException { - SessionRepositoryRequestWrapper.this.commitSession(); + SessionRepositoryRequestWrapper.this.commitSession(false); this.delegate.include(request, response); } diff --git a/spring-session-core/src/test/java/org/springframework/session/web/http/SessionRepositoryFilterTests.java b/spring-session-core/src/test/java/org/springframework/session/web/http/SessionRepositoryFilterTests.java index 127863290..e129aea41 100644 --- a/spring-session-core/src/test/java/org/springframework/session/web/http/SessionRepositoryFilterTests.java +++ b/spring-session-core/src/test/java/org/springframework/session/web/http/SessionRepositoryFilterTests.java @@ -1340,7 +1340,7 @@ public void doFilter(HttpServletRequest wrappedRequest, HttpServletResponse wrap } }); - verify(sessionRepository, times(2)).findById(eq(session.getId())); + verify(sessionRepository, times(1)).findById(eq(session.getId())); verify(sessionRepository).save(any()); verifyNoMoreInteractions(sessionRepository); }