diff --git a/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/web/ServerProperties.java b/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/web/ServerProperties.java index ca10a733535..3e6d21c95c3 100644 --- a/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/web/ServerProperties.java +++ b/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/web/ServerProperties.java @@ -329,6 +329,11 @@ public class ServerProperties { @DurationUnit(ChronoUnit.SECONDS) private Duration timeout = Duration.ofMinutes(30); + /** + * The maximum number of sessions that can be stored. + */ + private int maxSessions = 10_000; + @NestedConfigurationProperty private final Cookie cookie = new Cookie(); @@ -340,6 +345,14 @@ public class ServerProperties { this.timeout = timeout; } + public int getMaxSessions() { + return this.maxSessions; + } + + public void setMaxSessions(int maxSessions) { + this.maxSessions = maxSessions; + } + public Cookie getCookie() { return this.cookie; } diff --git a/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/web/reactive/WebFluxAutoConfiguration.java b/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/web/reactive/WebFluxAutoConfiguration.java index e9ebef36249..09f3f9237a7 100644 --- a/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/web/reactive/WebFluxAutoConfiguration.java +++ b/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/web/reactive/WebFluxAutoConfiguration.java @@ -332,7 +332,10 @@ public class WebFluxAutoConfiguration { public WebSessionManager webSessionManager(ObjectProvider webSessionIdResolver) { DefaultWebSessionManager webSessionManager = new DefaultWebSessionManager(); Duration timeout = this.serverProperties.getReactive().getSession().getTimeout(); - webSessionManager.setSessionStore(new MaxIdleTimeInMemoryWebSessionStore(timeout)); + int maxSessions = this.serverProperties.getReactive().getSession().getMaxSessions(); + MaxIdleTimeInMemoryWebSessionStore sessionStore = new MaxIdleTimeInMemoryWebSessionStore(timeout); + sessionStore.setMaxSessions(maxSessions); + webSessionManager.setSessionStore(sessionStore); webSessionIdResolver.ifAvailable(webSessionManager::setSessionIdResolver); return webSessionManager; } diff --git a/spring-boot-project/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/web/reactive/WebFluxAutoConfigurationTests.java b/spring-boot-project/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/web/reactive/WebFluxAutoConfigurationTests.java index 2340013df8e..276944fe0de 100644 --- a/spring-boot-project/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/web/reactive/WebFluxAutoConfigurationTests.java +++ b/spring-boot-project/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/web/reactive/WebFluxAutoConfigurationTests.java @@ -109,8 +109,11 @@ import org.springframework.web.server.i18n.AcceptHeaderLocaleContextResolver; import org.springframework.web.server.i18n.FixedLocaleContextResolver; import org.springframework.web.server.i18n.LocaleContextResolver; import org.springframework.web.server.session.CookieWebSessionIdResolver; +import org.springframework.web.server.session.DefaultWebSessionManager; +import org.springframework.web.server.session.InMemoryWebSessionStore; import org.springframework.web.server.session.WebSessionIdResolver; import org.springframework.web.server.session.WebSessionManager; +import org.springframework.web.server.session.WebSessionStore; import org.springframework.web.util.pattern.PathPattern; import static org.assertj.core.api.Assertions.assertThat; @@ -622,6 +625,20 @@ class WebFluxAutoConfigurationTests { }))); } + @Test + void customSessionMaxSessionsConfigurationShouldBeApplied() { + this.contextRunner.withPropertyValues("server.reactive.session.max-sessions:123") + .run((context) -> assertMaxSessionsWithWebSession(123)); + } + + @Test + void defaultSessionMaxSessionsConfigurationShouldBeInSync() { + this.contextRunner.run((context) -> { + int defaultMaxSessions = new InMemoryWebSessionStore().getMaxSessions(); + assertMaxSessionsWithWebSession(defaultMaxSessions); + }); + } + @Test void customSessionCookieConfigurationShouldBeApplied() { this.contextRunner.withPropertyValues("server.reactive.session.cookie.name:JSESSIONID", @@ -753,6 +770,16 @@ class WebFluxAutoConfigurationTests { }; } + private ContextConsumer assertMaxSessionsWithWebSession(int maxSessions) { + return (context) -> { + WebSessionManager sessionManager = context.getBean(WebSessionManager.class); + assertThat(sessionManager).isInstanceOf(DefaultWebSessionManager.class); + WebSessionStore sessionStore = ((DefaultWebSessionManager) sessionManager).getSessionStore(); + assertThat(sessionStore).isInstanceOf(InMemoryWebSessionStore.class); + assertThat(((InMemoryWebSessionStore) sessionStore).getMaxSessions()).isEqualTo(maxSessions); + }; + } + private Map getHandlerMap(ApplicationContext context) { HandlerMapping mapping = context.getBean("resourceHandlerMapping", HandlerMapping.class); if (mapping instanceof SimpleUrlHandlerMapping simpleMapping) {