From ed20edd1771d203687a5318fa9ac766c0babf909 Mon Sep 17 00:00:00 2001 From: Josh Cummings Date: Mon, 25 Jun 2018 16:44:03 -0600 Subject: [PATCH] Improved Session Creation Policy Configuration Other configurers can now offer their preference on session creation policy without trumping what a user provided via the sessionCreationPolicy method. This is valuable for configurer's like Resource Server that would like to have session management be stateless, but not at the expense of the user's direct configuration. Fixes: gh-5518 --- .../SessionManagementConfigurer.java | 22 ++-- ...tConfigurerSessionCreationPolicyTests.java | 115 ++++++++++++++++++ 2 files changed, 130 insertions(+), 7 deletions(-) create mode 100644 config/src/test/java/org/springframework/security/config/annotation/web/configurers/SessionManagementConfigurerSessionCreationPolicyTests.java diff --git a/config/src/main/java/org/springframework/security/config/annotation/web/configurers/SessionManagementConfigurer.java b/config/src/main/java/org/springframework/security/config/annotation/web/configurers/SessionManagementConfigurer.java index fd814edc7d..43ea86d7f0 100644 --- a/config/src/main/java/org/springframework/security/config/annotation/web/configurers/SessionManagementConfigurer.java +++ b/config/src/main/java/org/springframework/security/config/annotation/web/configurers/SessionManagementConfigurer.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2016 the original author or authors. + * Copyright 2002-2018 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. @@ -18,7 +18,6 @@ package org.springframework.security.config.annotation.web.configurers; import java.util.ArrayList; import java.util.Arrays; import java.util.List; - import javax.servlet.http.HttpServletResponse; import javax.servlet.http.HttpSession; @@ -105,7 +104,7 @@ public final class SessionManagementConfigurer> private Integer maximumSessions; private String expiredUrl; private boolean maxSessionsPreventsLogin; - private SessionCreationPolicy sessionPolicy = SessionCreationPolicy.IF_REQUIRED; + private SessionCreationPolicy sessionPolicy; private boolean enableSessionUrlRewriting; private String invalidSessionUrl; private String sessionAuthenticationErrorUrl; @@ -549,7 +548,14 @@ public final class SessionManagementConfigurer> * @return the {@link SessionCreationPolicy} */ SessionCreationPolicy getSessionCreationPolicy() { - return this.sessionPolicy; + if (this.sessionPolicy != null) { + return this.sessionPolicy; + } + + SessionCreationPolicy sessionPolicy = + getBuilder().getSharedObject(SessionCreationPolicy.class); + return sessionPolicy == null ? + SessionCreationPolicy.IF_REQUIRED : sessionPolicy; } /** @@ -558,8 +564,9 @@ public final class SessionManagementConfigurer> * @return true if the {@link SessionCreationPolicy} allows session creation */ private boolean isAllowSessionCreation() { - return SessionCreationPolicy.ALWAYS == this.sessionPolicy - || SessionCreationPolicy.IF_REQUIRED == this.sessionPolicy; + SessionCreationPolicy sessionPolicy = getSessionCreationPolicy(); + return SessionCreationPolicy.ALWAYS == sessionPolicy + || SessionCreationPolicy.IF_REQUIRED == sessionPolicy; } /** @@ -567,7 +574,8 @@ public final class SessionManagementConfigurer> * @return */ private boolean isStateless() { - return SessionCreationPolicy.STATELESS == this.sessionPolicy; + SessionCreationPolicy sessionPolicy = getSessionCreationPolicy(); + return SessionCreationPolicy.STATELESS == sessionPolicy; } /** diff --git a/config/src/test/java/org/springframework/security/config/annotation/web/configurers/SessionManagementConfigurerSessionCreationPolicyTests.java b/config/src/test/java/org/springframework/security/config/annotation/web/configurers/SessionManagementConfigurerSessionCreationPolicyTests.java new file mode 100644 index 0000000000..0d125b89f7 --- /dev/null +++ b/config/src/test/java/org/springframework/security/config/annotation/web/configurers/SessionManagementConfigurerSessionCreationPolicyTests.java @@ -0,0 +1,115 @@ +/* + * Copyright 2002-2018 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. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.springframework.security.config.annotation.web.configurers; + +import org.junit.Rule; +import org.junit.Test; + +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.security.config.annotation.web.builders.HttpSecurity; +import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity; +import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter; +import org.springframework.security.config.http.SessionCreationPolicy; +import org.springframework.security.config.test.SpringTestRule; +import org.springframework.test.web.servlet.MockMvc; +import org.springframework.test.web.servlet.MvcResult; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.RestController; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get; +import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; + +/** + * @author Josh Cummings + */ +public class SessionManagementConfigurerSessionCreationPolicyTests { + @Autowired + MockMvc mvc; + + @Rule + public final SpringTestRule spring = new SpringTestRule(); + + @Test + public void getWhenSharedObjectSessionCreationPolicyConfigurationThenOverrides() + throws Exception { + + this.spring.register(StatelessCreateSessionSharedObjectConfig.class).autowire(); + + MvcResult result = this.mvc.perform(get("/")).andReturn(); + + assertThat(result.getRequest().getSession(false)).isNull(); + } + + @EnableWebSecurity + static class StatelessCreateSessionSharedObjectConfig extends WebSecurityConfigurerAdapter { + @Override + protected void configure(HttpSecurity http) throws Exception { + super.configure(http); + http.setSharedObject(SessionCreationPolicy.class, SessionCreationPolicy.STATELESS); + } + } + + @Test + public void getWhenUserSessionCreationPolicyConfigurationThenOverrides() + throws Exception { + + this.spring.register(StatelessCreateSessionUserConfig.class).autowire(); + + MvcResult result = this.mvc.perform(get("/")).andReturn(); + + assertThat(result.getRequest().getSession(false)).isNull(); + } + + @EnableWebSecurity + static class StatelessCreateSessionUserConfig extends WebSecurityConfigurerAdapter { + @Override + protected void configure(HttpSecurity http) throws Exception { + super.configure(http); + http + .sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS); + + http.setSharedObject(SessionCreationPolicy.class, SessionCreationPolicy.ALWAYS); + } + } + + @Test + public void getWhenDefaultsThenLoginChallengeCreatesSession() + throws Exception { + + this.spring.register(DefaultConfig.class, BasicController.class).autowire(); + + MvcResult result = + this.mvc.perform(get("/")) + .andExpect(status().isUnauthorized()) + .andReturn(); + + assertThat(result.getRequest().getSession(false)).isNotNull(); + } + + @EnableWebSecurity + static class DefaultConfig extends WebSecurityConfigurerAdapter { + } + + @RestController + static class BasicController { + @GetMapping("/") + public String root() { + return "ok"; + } + } +}