Add SecurityContextHolderFilter

Closes gh-9635
This commit is contained in:
Rob Winch
2022-02-18 15:14:34 -06:00
parent dbcb5004b4
commit 87ed31a99c
22 changed files with 583 additions and 46 deletions

View File

@@ -16,6 +16,10 @@
package org.springframework.security.config.annotation.web.configurers;
import java.util.List;
import java.util.stream.Collectors;
import javax.servlet.Filter;
import javax.servlet.http.HttpSession;
import org.junit.jupiter.api.Test;
@@ -33,8 +37,11 @@ import org.springframework.security.config.test.SpringTestContext;
import org.springframework.security.config.test.SpringTestContextExtension;
import org.springframework.security.core.context.SecurityContext;
import org.springframework.security.core.userdetails.PasswordEncodedUser;
import org.springframework.security.web.FilterChainProxy;
import org.springframework.security.web.context.HttpRequestResponseHolder;
import org.springframework.security.web.context.HttpSessionSecurityContextRepository;
import org.springframework.security.web.context.NullSecurityContextRepository;
import org.springframework.security.web.context.SecurityContextHolderFilter;
import org.springframework.security.web.context.SecurityContextPersistenceFilter;
import org.springframework.security.web.context.SecurityContextRepository;
import org.springframework.security.web.context.request.async.WebAsyncManagerIntegrationFilter;
@@ -110,6 +117,27 @@ public class SecurityContextConfigurerTests {
assertThat(session).isNull();
}
@Test
public void requireExplicitSave() throws Exception {
HttpSessionSecurityContextRepository repository = new HttpSessionSecurityContextRepository();
SpringTestContext testContext = this.spring.register(RequireExplicitSaveConfig.class);
testContext.autowire();
FilterChainProxy filterChainProxy = testContext.getContext().getBean(FilterChainProxy.class);
// @formatter:off
List<Class<? extends Filter>> filterTypes = filterChainProxy.getFilters("/")
.stream()
.map(Filter::getClass)
.collect(Collectors.toList());
assertThat(filterTypes)
.contains(SecurityContextHolderFilter.class)
.doesNotContain(SecurityContextPersistenceFilter.class);
// @formatter:on
MvcResult mvcResult = this.mvc.perform(formLogin()).andReturn();
SecurityContext securityContext = repository
.loadContext(new HttpRequestResponseHolder(mvcResult.getRequest(), mvcResult.getResponse()));
assertThat(securityContext.getAuthentication()).isNotNull();
}
@EnableWebSecurity
static class ObjectPostProcessorConfig extends WebSecurityConfigurerAdapter {
@@ -241,14 +269,39 @@ public class SecurityContextConfigurerTests {
@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
}
}
@EnableWebSecurity
static class RequireExplicitSaveConfig extends WebSecurityConfigurerAdapter {
@Override
protected void configure(HttpSecurity http) throws Exception {
// @formatter:off
http
.formLogin(withDefaults())
.securityContext((securityContext) ->
securityContext
.securityContextRepository(new NullSecurityContextRepository())
.securityContext((securityContext) -> securityContext
.requireExplicitSave(true)
);
// @formatter:on
}
@@ -258,7 +311,7 @@ public class SecurityContextConfigurerTests {
// @formatter:off
auth
.inMemoryAuthentication()
.withUser(PasswordEncodedUser.user());
.withUser(PasswordEncodedUser.user());
// @formatter:on
}

View File

@@ -122,9 +122,11 @@ import static org.mockito.BDDMockito.willAnswer;
import static org.mockito.Mockito.atLeastOnce;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.verify;
import static org.springframework.security.test.web.servlet.request.SecurityMockMvcRequestBuilders.formLogin;
import static org.springframework.security.test.web.servlet.request.SecurityMockMvcRequestPostProcessors.csrf;
import static org.springframework.security.test.web.servlet.request.SecurityMockMvcRequestPostProcessors.httpBasic;
import static org.springframework.security.test.web.servlet.request.SecurityMockMvcRequestPostProcessors.x509;
import static org.springframework.security.test.web.servlet.response.SecurityMockMvcResultMatchers.authenticated;
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.delete;
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get;
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.post;
@@ -462,6 +464,37 @@ public class MiscHttpConfigTests {
any(HttpServletResponse.class));
}
@Test
public void getWhenExplicitSaveAndRepositoryAndAuthenticatingThenConsultsCustomSecurityContextRepository()
throws Exception {
this.spring.configLocations(xml("ExplicitSaveAndExplicitRepository")).autowire();
SecurityContextRepository repository = this.spring.getContext().getBean(SecurityContextRepository.class);
SecurityContext context = new SecurityContextImpl(new TestingAuthenticationToken("user", "password"));
given(repository.loadContext(any(HttpRequestResponseHolder.class))).willReturn(context);
// @formatter:off
MvcResult result = this.mvc.perform(formLogin())
.andExpect(status().is3xxRedirection())
.andExpect(authenticated())
.andReturn();
// @formatter:on
verify(repository, atLeastOnce()).saveContext(any(SecurityContext.class), any(HttpServletRequest.class),
any(HttpServletResponse.class));
}
@Test
public void getWhenExplicitSaveAndExplicitSaveAndAuthenticatingThenConsultsCustomSecurityContextRepository()
throws Exception {
this.spring.configLocations(xml("ExplicitSave")).autowire();
SecurityContextRepository repository = this.spring.getContext().getBean(SecurityContextRepository.class);
// @formatter:off
MvcResult result = this.mvc.perform(formLogin())
.andExpect(status().is3xxRedirection())
.andReturn();
// @formatter:on
assertThat(repository.loadContext(new HttpRequestResponseHolder(result.getRequest(), result.getResponse()))
.getAuthentication()).isNotNull();
}
@Test
public void getWhenUsingInterceptUrlExpressionsThenAuthorizesAccordingly() throws Exception {
this.spring.configLocations(xml("InterceptUrlExpressions")).autowire();