diff --git a/config/src/main/java/org/springframework/security/config/annotation/web/builders/HttpSecurity.java b/config/src/main/java/org/springframework/security/config/annotation/web/builders/HttpSecurity.java
index e7397d9c04..21bc5d22a3 100644
--- a/config/src/main/java/org/springframework/security/config/annotation/web/builders/HttpSecurity.java
+++ b/config/src/main/java/org/springframework/security/config/annotation/web/builders/HttpSecurity.java
@@ -62,6 +62,7 @@ import org.springframework.security.web.PortMapper;
import org.springframework.security.web.PortMapperImpl;
import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;
import org.springframework.security.web.context.AbstractSecurityWebApplicationInitializer;
+import org.springframework.security.web.context.SecurityContextRepository;
import org.springframework.security.web.servlet.util.matcher.MvcRequestMatcher;
import org.springframework.security.web.session.HttpSessionEventPublisher;
import org.springframework.security.web.util.matcher.AntPathRequestMatcher;
@@ -1248,6 +1249,39 @@ public final class HttpSecurity extends
return getOrApply(new SecurityContextConfigurer<>());
}
+ /**
+ * Sets up management of the {@link SecurityContext} on the
+ * {@link SecurityContextHolder} between {@link HttpServletRequest}'s. This is
+ * automatically applied when using {@link WebSecurityConfigurerAdapter}.
+ *
+ * The following customization specifies the shared {@link SecurityContextRepository}
+ *
+ *
+ * @Configuration
+ * @EnableWebSecurity
+ * public class SecurityContextSecurityConfig extends WebSecurityConfigurerAdapter {
+ *
+ * @Override
+ * protected void configure(HttpSecurity http) throws Exception {
+ * http
+ * .securityContext(securityContext ->
+ * securityContext
+ * .securityContextRepository(SCR)
+ * );
+ * }
+ * }
+ *
+ *
+ * @param securityContextCustomizer the {@link Customizer} to provide more options for
+ * the {@link SecurityContextConfigurer}
+ * @return the {@link HttpSecurity} for further customizations
+ * @throws Exception
+ */
+ public HttpSecurity securityContext(Customizer> securityContextCustomizer) throws Exception {
+ securityContextCustomizer.customize(getOrApply(new SecurityContextConfigurer<>()));
+ return HttpSecurity.this;
+ }
+
/**
* Integrates the {@link HttpServletRequest} methods with the values found on the
* {@link SecurityContext}. This is automatically applied when using
diff --git a/config/src/test/java/org/springframework/security/config/annotation/web/configurers/SecurityContextConfigurerTests.java b/config/src/test/java/org/springframework/security/config/annotation/web/configurers/SecurityContextConfigurerTests.java
index b9b0939344..5d0419d959 100644
--- a/config/src/test/java/org/springframework/security/config/annotation/web/configurers/SecurityContextConfigurerTests.java
+++ b/config/src/test/java/org/springframework/security/config/annotation/web/configurers/SecurityContextConfigurerTests.java
@@ -28,14 +28,22 @@ import org.springframework.security.config.annotation.web.configuration.EnableWe
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.config.test.SpringTestRule;
import org.springframework.security.core.context.SecurityContext;
+import org.springframework.security.core.userdetails.PasswordEncodedUser;
import org.springframework.security.web.context.HttpRequestResponseHolder;
+import org.springframework.security.web.context.NullSecurityContextRepository;
import org.springframework.security.web.context.SecurityContextPersistenceFilter;
import org.springframework.security.web.context.SecurityContextRepository;
import org.springframework.security.web.context.request.async.WebAsyncManagerIntegrationFilter;
import org.springframework.test.web.servlet.MockMvc;
+import org.springframework.test.web.servlet.MvcResult;
+import javax.servlet.http.HttpSession;
+
+import static org.assertj.core.api.Assertions.assertThat;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.Mockito.*;
+import static org.springframework.security.config.Customizer.withDefaults;
+import static org.springframework.security.test.web.servlet.request.SecurityMockMvcRequestBuilders.formLogin;
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get;
/**
@@ -151,4 +159,97 @@ public class SecurityContextConfigurerTests {
// @formatter:on
}
}
+
+ @Test
+ public void requestWhenSecurityContextWithDefaultsInLambdaThenSessionIsCreated() throws Exception {
+ this.spring.register(SecurityContextWithDefaultsInLambdaConfig.class).autowire();
+
+ MvcResult mvcResult = this.mvc.perform(formLogin()).andReturn();
+ HttpSession session = mvcResult.getRequest().getSession(false);
+ assertThat(session).isNotNull();
+ }
+
+ @EnableWebSecurity
+ static class SecurityContextWithDefaultsInLambdaConfig extends WebSecurityConfigurerAdapter {
+ @Override
+ protected void configure(HttpSecurity http) throws Exception {
+ // @formatter:off
+ http
+ .formLogin(withDefaults())
+ .securityContext(withDefaults());
+ // @formatter:on
+ }
+
+ @Override
+ protected void configure(AuthenticationManagerBuilder auth) throws Exception {
+ // @formatter:off
+ auth
+ .inMemoryAuthentication()
+ .withUser(PasswordEncodedUser.user());
+ // @formatter:on
+ }
+ }
+
+ @Test
+ public void requestWhenSecurityContextDisabledInLambdaThenContextNotSavedInSession() throws Exception {
+ this.spring.register(SecurityContextDisabledInLambdaConfig.class).autowire();
+
+ MvcResult mvcResult = this.mvc.perform(formLogin()).andReturn();
+ HttpSession session = mvcResult.getRequest().getSession(false);
+ assertThat(session).isNull();
+ }
+
+ @EnableWebSecurity
+ static class SecurityContextDisabledInLambdaConfig extends WebSecurityConfigurerAdapter {
+ @Override
+ protected void configure(HttpSecurity http) throws Exception {
+ // @formatter:off
+ http
+ .formLogin(withDefaults())
+ .securityContext(AbstractHttpConfigurer::disable);
+ // @formatter:on
+ }
+
+ @Override
+ protected void configure(AuthenticationManagerBuilder auth) throws Exception {
+ // @formatter:off
+ auth
+ .inMemoryAuthentication()
+ .withUser(PasswordEncodedUser.user());
+ // @formatter:on
+ }
+ }
+
+ @Test
+ public void requestWhenNullSecurityContextRepositoryInLambdaThenContextNotSavedInSession() throws Exception {
+ this.spring.register(NullSecurityContextRepositoryInLambdaConfig.class).autowire();
+
+ MvcResult mvcResult = this.mvc.perform(formLogin()).andReturn();
+ HttpSession session = mvcResult.getRequest().getSession(false);
+ assertThat(session).isNull();
+ }
+
+ @EnableWebSecurity
+ static class NullSecurityContextRepositoryInLambdaConfig extends WebSecurityConfigurerAdapter {
+ @Override
+ protected void configure(HttpSecurity http) throws Exception {
+ // @formatter:off
+ http
+ .formLogin(withDefaults())
+ .securityContext(securityContext ->
+ securityContext
+ .securityContextRepository(new NullSecurityContextRepository())
+ );
+ // @formatter:on
+ }
+
+ @Override
+ protected void configure(AuthenticationManagerBuilder auth) throws Exception {
+ // @formatter:off
+ auth
+ .inMemoryAuthentication()
+ .withUser(PasswordEncodedUser.user());
+ // @formatter:on
+ }
+ }
}