Use SecurityContextHolderStrategy for Remember-me

Issue gh-11060
Isuse gh-11061
This commit is contained in:
Josh Cummings
2022-06-21 16:42:47 -06:00
parent ee66850aed
commit 4a2d77d3f2
7 changed files with 114 additions and 15 deletions

View File

@@ -31,12 +31,14 @@ import org.springframework.mock.web.MockHttpSession;
import org.springframework.security.authentication.RememberMeAuthenticationToken;
import org.springframework.security.authentication.dao.DaoAuthenticationProvider;
import org.springframework.security.config.annotation.ObjectPostProcessor;
import org.springframework.security.config.annotation.SecurityContextChangedListenerConfig;
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
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.test.SpringTestContext;
import org.springframework.security.config.test.SpringTestContextExtension;
import org.springframework.security.core.context.SecurityContextHolderStrategy;
import org.springframework.security.core.userdetails.PasswordEncodedUser;
import org.springframework.security.core.userdetails.User;
import org.springframework.security.core.userdetails.UserDetailsService;
@@ -56,6 +58,7 @@ import static org.assertj.core.api.Assertions.assertThatIllegalStateException;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.anyString;
import static org.mockito.BDDMockito.given;
import static org.mockito.Mockito.atLeastOnce;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.spy;
import static org.mockito.Mockito.verify;
@@ -101,7 +104,8 @@ public class RememberMeConfigurerTests {
@Test
public void configureWhenRegisteringObjectPostProcessorThenInvokedOnRememberMeAuthenticationFilter() {
this.spring.register(ObjectPostProcessorConfig.class).autowire();
verify(ObjectPostProcessorConfig.objectPostProcessor).postProcess(any(RememberMeAuthenticationFilter.class));
verify(this.spring.getContext().getBean(ObjectPostProcessor.class))
.postProcess(any(RememberMeAuthenticationFilter.class));
}
@Test
@@ -132,6 +136,21 @@ public class RememberMeConfigurerTests {
this.mvc.perform(request).andExpect(remembermeAuthentication);
}
@Test
public void rememberMeWhenCustomSecurityContextHolderStrategyThenUses() throws Exception {
this.spring.register(UserDetailsServiceBeanConfig.class, SecurityContextChangedListenerConfig.class).autowire();
MvcResult mvcResult = this.mvc.perform(post("/login").with(csrf()).param("username", "user")
.param("password", "password").param("remember-me", "true")).andReturn();
Cookie rememberMeCookie = mvcResult.getResponse().getCookie("remember-me");
// @formatter:off
MockHttpServletRequestBuilder request = get("/abc").cookie(rememberMeCookie);
SecurityMockMvcResultMatchers.AuthenticatedMatcher remembermeAuthentication = authenticated()
.withAuthentication((auth) -> assertThat(auth).isInstanceOf(RememberMeAuthenticationToken.class));
// @formatter:on
this.mvc.perform(request).andExpect(remembermeAuthentication);
verify(this.spring.getContext().getBean(SecurityContextHolderStrategy.class), atLeastOnce()).getContext();
}
@Test
public void loginWhenRememberMeTrueThenRespondsWithRememberMeCookie() throws Exception {
this.spring.register(RememberMeConfig.class).autowire();
@@ -316,14 +335,14 @@ public class RememberMeConfigurerTests {
@EnableWebSecurity
static class ObjectPostProcessorConfig extends WebSecurityConfigurerAdapter {
static ObjectPostProcessor<Object> objectPostProcessor = spy(ReflectingObjectPostProcessor.class);
ObjectPostProcessor<Object> objectPostProcessor = spy(ReflectingObjectPostProcessor.class);
@Override
protected void configure(HttpSecurity http) throws Exception {
// @formatter:off
http
.rememberMe()
.userDetailsService(new AuthenticationManagerBuilder(objectPostProcessor).getDefaultUserDetailsService());
.userDetailsService(new AuthenticationManagerBuilder(this.objectPostProcessor).getDefaultUserDetailsService());
// @formatter:on
}
@@ -336,8 +355,8 @@ public class RememberMeConfigurerTests {
}
@Bean
static ObjectPostProcessor<Object> objectPostProcessor() {
return objectPostProcessor;
ObjectPostProcessor<Object> objectPostProcessor() {
return this.objectPostProcessor;
}
}

View File

@@ -30,6 +30,7 @@ import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.security.TestDataSource;
import org.springframework.security.config.test.SpringTestContext;
import org.springframework.security.config.test.SpringTestContextExtension;
import org.springframework.security.core.context.SecurityContextHolderStrategy;
import org.springframework.security.core.userdetails.User;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.web.authentication.rememberme.AbstractRememberMeServices;
@@ -220,6 +221,18 @@ public class RememberMeConfigTests {
() -> this.spring.configLocations(xml("NegativeTokenValidityWithPersistentRepository")).autowire());
}
@Test
public void rememberMeWhenCustomSecurityContextHolderStrategyThenUses() throws Exception {
this.spring.configLocations(xml("WithSecurityContextHolderStrategy")).autowire();
MvcResult result = rememberAuthentication("user", "password").andReturn();
Cookie cookie = rememberMeCookie(result);
// @formatter:off
this.mvc.perform(get("/authenticated").cookie(cookie))
.andExpect(status().isOk());
// @formatter:on
verify(this.spring.getContext().getBean(SecurityContextHolderStrategy.class), atLeastOnce()).getContext();
}
@Test
public void requestWithRememberMeWhenUsingCustomUserDetailsServiceThenInvokesThisUserDetailsService()
throws Exception {