diff --git a/config/src/main/java/org/springframework/security/config/http/HttpConfigurationBuilder.java b/config/src/main/java/org/springframework/security/config/http/HttpConfigurationBuilder.java index 992d5c60a1..adb6b89569 100644 --- a/config/src/main/java/org/springframework/security/config/http/HttpConfigurationBuilder.java +++ b/config/src/main/java/org/springframework/security/config/http/HttpConfigurationBuilder.java @@ -387,7 +387,8 @@ class HttpConfigurationBuilder { concurrentSessionStrategy = BeanDefinitionBuilder .rootBeanDefinition(ConcurrentSessionControlAuthenticationStrategy.class); concurrentSessionStrategy.addConstructorArgValue(this.sessionRegistryRef); - String maxSessions = sessionCtrlElt.getAttribute("max-sessions"); + String maxSessions = this.pc.getReaderContext().getEnvironment() + .resolvePlaceholders(sessionCtrlElt.getAttribute("max-sessions")); if (StringUtils.hasText(maxSessions)) { concurrentSessionStrategy.addPropertyValue("maximumSessions", maxSessions); } diff --git a/config/src/main/resources/org/springframework/security/config/spring-security-5.5.rnc b/config/src/main/resources/org/springframework/security/config/spring-security-5.5.rnc index 8fab2d648f..4d94b28a54 100644 --- a/config/src/main/resources/org/springframework/security/config/spring-security-5.5.rnc +++ b/config/src/main/resources/org/springframework/security/config/spring-security-5.5.rnc @@ -714,7 +714,7 @@ concurrency-control = concurrency-control.attlist &= ## The maximum number of sessions a single authenticated user can have open at the same time. Defaults to "1". A negative value denotes unlimited sessions. - attribute max-sessions {xsd:integer}? + attribute max-sessions {xsd:token}? concurrency-control.attlist &= ## The URL a user will be redirected to if they attempt to use a session which has been "expired" because they have logged in again. attribute expired-url {xsd:token}? diff --git a/config/src/main/resources/org/springframework/security/config/spring-security-5.5.xsd b/config/src/main/resources/org/springframework/security/config/spring-security-5.5.xsd index 4c1e7f9182..74bb4fe019 100644 --- a/config/src/main/resources/org/springframework/security/config/spring-security-5.5.xsd +++ b/config/src/main/resources/org/springframework/security/config/spring-security-5.5.xsd @@ -2161,7 +2161,7 @@ - + The maximum number of sessions a single authenticated user can have open at the same time. Defaults to "1". A negative value denotes unlimited sessions. diff --git a/config/src/test/java/org/springframework/security/config/http/SessionManagementConfigTests.java b/config/src/test/java/org/springframework/security/config/http/SessionManagementConfigTests.java index f75a2edc4b..58bca95582 100644 --- a/config/src/test/java/org/springframework/security/config/http/SessionManagementConfigTests.java +++ b/config/src/test/java/org/springframework/security/config/http/SessionManagementConfigTests.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2018 the original author or authors. + * Copyright 2002-2020 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -79,6 +79,7 @@ import static org.springframework.test.web.servlet.result.MockMvcResultMatchers. * @author Rob Winch * @author Josh Cummings * @author Onur Kagan Ozcan + * @author Mazen Aissa */ public class SessionManagementConfigTests { @@ -356,6 +357,18 @@ public class SessionManagementConfigTests { // @formatter:on } + @Test + public void requestWhenMaxSessionsIsSetWithPlaceHolderThenErrorsWhenExceeded() throws Exception { + System.setProperty("sessionManagement.maxSessions", "1"); + this.spring.configLocations(xml("ConcurrencyControlMaxSessionsPlaceHolder")).autowire(); + // @formatter:off + this.mvc.perform(get("/auth").with(httpBasic("user", "password"))) + .andExpect(status().isOk()); + this.mvc.perform(get("/auth").with(httpBasic("user", "password"))) + .andExpect(redirectedUrl("/max-exceeded")); + // @formatter:on + } + @Test public void autowireWhenSessionFixationProtectionIsNoneAndCsrfDisabledThenSessionManagementFilterIsNotWired() { this.spring.configLocations(xml("NoSessionManagementFilter")).autowire(); diff --git a/config/src/test/resources/org/springframework/security/config/http/SessionManagementConfigTests-ConcurrencyControlMaxSessionsPlaceHolder.xml b/config/src/test/resources/org/springframework/security/config/http/SessionManagementConfigTests-ConcurrencyControlMaxSessionsPlaceHolder.xml new file mode 100644 index 0000000000..1c23bf62bf --- /dev/null +++ b/config/src/test/resources/org/springframework/security/config/http/SessionManagementConfigTests-ConcurrencyControlMaxSessionsPlaceHolder.xml @@ -0,0 +1,33 @@ + + + + + + + + + + + + + + + \ No newline at end of file