Skip to content

Commit

Permalink
RememberMeConfigurer Picks Up SecurityContextRepository
Browse files Browse the repository at this point in the history
Closes gh-13104
  • Loading branch information
jzheaux committed May 2, 2023
1 parent 6d37ca1 commit e9a02bc
Show file tree
Hide file tree
Showing 2 changed files with 87 additions and 2 deletions.
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* Copyright 2002-2022 the original author or authors.
* Copyright 2002-2023 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.
Expand Down Expand Up @@ -35,6 +35,7 @@
import org.springframework.security.web.authentication.rememberme.RememberMeAuthenticationFilter;
import org.springframework.security.web.authentication.rememberme.TokenBasedRememberMeServices;
import org.springframework.security.web.authentication.ui.DefaultLoginPageGeneratingFilter;
import org.springframework.security.web.context.SecurityContextRepository;
import org.springframework.util.Assert;

/**
Expand Down Expand Up @@ -288,6 +289,12 @@ public void configure(H http) {
if (this.authenticationSuccessHandler != null) {
rememberMeFilter.setAuthenticationSuccessHandler(this.authenticationSuccessHandler);
}
SecurityContextConfigurer<?> securityContextConfigurer = http.getConfigurer(SecurityContextConfigurer.class);
if (securityContextConfigurer != null && securityContextConfigurer.isRequireExplicitSave()) {
SecurityContextRepository securityContextRepository = securityContextConfigurer
.getSecurityContextRepository();
rememberMeFilter.setSecurityContextRepository(securityContextRepository);
}
rememberMeFilter.setSecurityContextHolderStrategy(getSecurityContextHolderStrategy());
rememberMeFilter = postProcess(rememberMeFilter);
http.addFilter(rememberMeFilter);
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* Copyright 2002-2022 the original author or authors.
* Copyright 2002-2023 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.
Expand All @@ -19,6 +19,8 @@
import java.util.Collections;

import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;

import org.junit.jupiter.api.Test;
Expand All @@ -38,6 +40,7 @@
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.SecurityContext;
import org.springframework.security.core.context.SecurityContextHolderStrategy;
import org.springframework.security.core.userdetails.PasswordEncodedUser;
import org.springframework.security.core.userdetails.User;
Expand All @@ -48,6 +51,9 @@
import org.springframework.security.web.authentication.RememberMeServices;
import org.springframework.security.web.authentication.rememberme.RememberMeAuthenticationFilter;
import org.springframework.security.web.authentication.rememberme.TokenBasedRememberMeServices;
import org.springframework.security.web.context.HttpRequestResponseHolder;
import org.springframework.security.web.context.HttpSessionSecurityContextRepository;
import org.springframework.security.web.context.SecurityContextRepository;
import org.springframework.test.web.servlet.MockMvc;
import org.springframework.test.web.servlet.MvcResult;
import org.springframework.test.web.servlet.request.MockHttpServletRequestBuilder;
Expand All @@ -60,6 +66,7 @@
import static org.mockito.BDDMockito.given;
import static org.mockito.Mockito.atLeastOnce;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.reset;
import static org.mockito.Mockito.spy;
import static org.mockito.Mockito.verify;
import static org.springframework.security.config.Customizer.withDefaults;
Expand Down Expand Up @@ -303,6 +310,24 @@ public void getWhenRememberMeCookieAndNoKeyConfiguredThenKeyFromRememberMeServic
this.mvc.perform(requestWithRememberme).andExpect(remembermeAuthentication);
}

// gh-13104
@Test
public void getWhenCustomSecurityContextRepositoryThenUses() throws Exception {
this.spring.register(SecurityContextRepositoryConfig.class).autowire();
SecurityContextRepository repository = this.spring.getContext().getBean(SecurityContextRepository.class);
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");
reset(repository);
// @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(repository).saveContext(any(), any(), any());
}

@EnableWebSecurity
static class NullUserDetailsConfig extends WebSecurityConfigurerAdapter {

Expand Down Expand Up @@ -582,4 +607,57 @@ protected void configure(HttpSecurity http) throws Exception {

}

@EnableWebSecurity
static class SecurityContextRepositoryConfig {

private SecurityContextRepository repository = spy(new SpySecurityContextRepository());

@Bean
SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
// @formatter:off
http
.authorizeHttpRequests((authorize) -> authorize.anyRequest().authenticated())
.securityContext((context) -> context
.requireExplicitSave(true)
.securityContextRepository(this.repository)
)
.formLogin(withDefaults())
.rememberMe(withDefaults());
return http.build();
// @formatter:on
}

@Bean
SecurityContextRepository securityContextRepository() {
return this.repository;
}

@Bean
UserDetailsService userDetailsService() {
return new InMemoryUserDetailsManager(PasswordEncodedUser.user());
}

private static class SpySecurityContextRepository implements SecurityContextRepository {

SecurityContextRepository delegate = new HttpSessionSecurityContextRepository();

@Override
public SecurityContext loadContext(HttpRequestResponseHolder requestResponseHolder) {
return this.delegate.loadContext(requestResponseHolder);
}

@Override
public void saveContext(SecurityContext context, HttpServletRequest request, HttpServletResponse response) {
this.delegate.saveContext(context, request, response);
}

@Override
public boolean containsContext(HttpServletRequest request) {
return this.delegate.containsContext(request);
}

}

}

}

0 comments on commit e9a02bc

Please sign in to comment.