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..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); } } @@ -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; @@ -211,8 +213,13 @@ 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; + } HttpSessionWrapper wrappedSession = getCurrentSession(); if (wrappedSession == null) { if (isInvalidateClientSession()) { @@ -221,13 +228,16 @@ 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())) { SessionRepositoryFilter.this.httpSessionIdResolver.setSessionId(this, this.response, sessionId); } } + this.sessionCommitted = true; } @SuppressWarnings("unchecked") @@ -409,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 7b2be3241..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 @@ -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(1)).findById(eq(session.getId())); + verify(sessionRepository).save(any()); + verifyNoMoreInteractions(sessionRepository); + } + // --- order @Test