Allow configuration of security context through nested builder

Issue: gh-5557
This commit is contained in:
Eleftheria Stein 2019-07-03 14:41:50 -04:00
parent 81d3cf1e7b
commit 04e0dcfe61
2 changed files with 135 additions and 0 deletions

View File

@ -62,6 +62,7 @@ import org.springframework.security.web.PortMapper;
import org.springframework.security.web.PortMapperImpl; import org.springframework.security.web.PortMapperImpl;
import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter; import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;
import org.springframework.security.web.context.AbstractSecurityWebApplicationInitializer; 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.servlet.util.matcher.MvcRequestMatcher;
import org.springframework.security.web.session.HttpSessionEventPublisher; import org.springframework.security.web.session.HttpSessionEventPublisher;
import org.springframework.security.web.util.matcher.AntPathRequestMatcher; import org.springframework.security.web.util.matcher.AntPathRequestMatcher;
@ -1248,6 +1249,39 @@ public final class HttpSecurity extends
return getOrApply(new SecurityContextConfigurer<>()); 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}
*
* <pre>
* &#064;Configuration
* &#064;EnableWebSecurity
* public class SecurityContextSecurityConfig extends WebSecurityConfigurerAdapter {
*
* &#064;Override
* protected void configure(HttpSecurity http) throws Exception {
* http
* .securityContext(securityContext ->
* securityContext
* .securityContextRepository(SCR)
* );
* }
* }
* </pre>
*
* @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<SecurityContextConfigurer<HttpSecurity>> securityContextCustomizer) throws Exception {
securityContextCustomizer.customize(getOrApply(new SecurityContextConfigurer<>()));
return HttpSecurity.this;
}
/** /**
* Integrates the {@link HttpServletRequest} methods with the values found on the * Integrates the {@link HttpServletRequest} methods with the values found on the
* {@link SecurityContext}. This is automatically applied when using * {@link SecurityContext}. This is automatically applied when using

View File

@ -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.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.config.test.SpringTestRule; import org.springframework.security.config.test.SpringTestRule;
import org.springframework.security.core.context.SecurityContext; 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.HttpRequestResponseHolder;
import org.springframework.security.web.context.NullSecurityContextRepository;
import org.springframework.security.web.context.SecurityContextPersistenceFilter; import org.springframework.security.web.context.SecurityContextPersistenceFilter;
import org.springframework.security.web.context.SecurityContextRepository; import org.springframework.security.web.context.SecurityContextRepository;
import org.springframework.security.web.context.request.async.WebAsyncManagerIntegrationFilter; import org.springframework.security.web.context.request.async.WebAsyncManagerIntegrationFilter;
import org.springframework.test.web.servlet.MockMvc; 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.ArgumentMatchers.any;
import static org.mockito.Mockito.*; 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; import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get;
/** /**
@ -151,4 +159,97 @@ public class SecurityContextConfigurerTests {
// @formatter:on // @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
}
}
} }