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
This commit is contained in:
Josh Cummings 2018-06-25 16:44:03 -06:00 committed by Rob Winch
parent 3c46727be1
commit ed20edd177
2 changed files with 130 additions and 7 deletions

View File

@ -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<H extends HttpSecurityBuilder<H>>
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<H extends HttpSecurityBuilder<H>>
* @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<H extends HttpSecurityBuilder<H>>
* @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<H extends HttpSecurityBuilder<H>>
* @return
*/
private boolean isStateless() {
return SessionCreationPolicy.STATELESS == this.sessionPolicy;
SessionCreationPolicy sessionPolicy = getSessionCreationPolicy();
return SessionCreationPolicy.STATELESS == sessionPolicy;
}
/**

View File

@ -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";
}
}
}